"Hey Siri, kahve sipariş et" — bu cümle, senin uygulamanla da çalışabilir. App Intents framework, iOS 16+ ile gelen modern intent sistemidir. Siri, Shortcuts uygulaması, Spotlight ve Interactive Widgets ile entegrasyon sağlar. Kullanıcıların uygulamanı açmadan işlem yapmasını sağla.
💡 Hızlı Not: App Intents, eski SiriKit Intents framework'ünün yerini alıyor. Yeni projeler için App Intents kullanmalısın.
İçindekiler
- App Intents Nedir?
- İlk Intent: @AppIntent
- Parametreler ve Entity
- App Shortcuts (Otomatik)
- Siri Integration
- Spotlight Donations
- Interactive Widgets ile Intents
- Focus Filters
- SiriKit → App Intents Migration
- Best Practices
App Intents Nedir? {#app-intents-nedir}
App Intents, uygulamanın fonksiyonlarını sistem seviyesinde kullanılabilir kılan bir framework. Üç temel kavram:
Kavram | Açıklama | Örnek |
|---|---|---|
AppIntent | Bir eylem tanımı | "Sipariş oluştur" |
AppEntity | Bir veri objesi | "Ürün", "Sipariş" |
AppShortcut | Otomatik Siri shortcut | "Hey Siri, [App] ile sipariş et" |
İlk Intent: @AppIntent {#ilk-intent}
swift
1import AppIntents2 3struct OrderCoffeeIntent: AppIntent {4 static var title: LocalizedStringResource = "Kahve Sipariş Et"5 static var description = IntentDescription("Favori kahvenizi sipariş edin")6 7 // Parametreler8 @Parameter(title: "Kahve Tipi")9 var coffeeType: CoffeeType10 11 @Parameter(title: "Boyut", default: .medium)12 var size: CoffeeSize13 14 // Intent çalıştır15 func perform() async throws -> some IntentResult & ProvidesDialog {16 let order = try await OrderService.shared.place(type: coffeeType, size: size)17 return .result(dialog: "\(coffeeType.name) \(size.name) siparişiniz alındı! Sipariş #\(order.id)")18 }19 20 // Parametre önerileri21 static var parameterSummary: some ParameterSummary {22 Summary("\(\.$size) \(\.$coffeeType) sipariş et")23 }24}25 26// Enum parameter27enum CoffeeType: String, AppEnum {28 case latte, cappuccino, americano, espresso29 30 static var typeDisplayRepresentation: TypeDisplayRepresentation = "Kahve Tipi"31 static var caseDisplayRepresentations: [CoffeeType: DisplayRepresentation] = [32 .latte: "Latte",33 .cappuccino: "Cappuccino",34 .americano: "Americano",35 .espresso: "Espresso",36 ]37}38 39enum CoffeeSize: String, AppEnum {40 case small, medium, large41 42 static var typeDisplayRepresentation: TypeDisplayRepresentation = "Boyut"43 static var caseDisplayRepresentations: [CoffeeSize: DisplayRepresentation] = [44 .small: "Küçük",45 .medium: "Orta",46 .large: "Büyük",47 ]48}Parametreler ve Entity {#parametreler}
swift
1// AppEntity - Shortcuts'ta seçilebilir veri objesi2struct ProductEntity: AppEntity {3 var id: UUID4 var name: String5 var price: Decimal6 var category: String7 8 static var typeDisplayRepresentation: TypeDisplayRepresentation = "Ürün"9 var displayRepresentation: DisplayRepresentation {10 DisplayRepresentation(title: "\(name)", subtitle: "\(price) TL")11 }12 13 // Arama desteği14 static var defaultQuery = ProductQuery()15}16 17struct ProductQuery: EntityQuery {18 func entities(for identifiers: [UUID]) async throws -> [ProductEntity] {19 try await ProductService.shared.getProducts(ids: identifiers)20 }21 22 func suggestedEntities() async throws -> [ProductEntity] {23 try await ProductService.shared.getPopularProducts()24 }25}App Shortcuts (Otomatik) {#app-shortcuts}
swift
1// App Shortcuts Provider - Siri'de otomatik görünür2struct MyAppShortcuts: AppShortcutsProvider {3 static var appShortcuts: [AppShortcut] {4 AppShortcut(5 intent: OrderCoffeeIntent(),6 phrases: [7 "\(.applicationName) ile kahve sipariş et",8 "\(.applicationName) kahve",9 "\(.applicationName) ile \(\.$coffeeType) sipariş et",10 ],11 shortTitle: "Kahve Sipariş",12 systemImageName: "cup.and.saucer.fill"13 )14 15 AppShortcut(16 intent: CheckOrderStatusIntent(),17 phrases: [18 "\(.applicationName) sipariş durumu",19 "\(.applicationName) siparişim nerede",20 ],21 shortTitle: "Sipariş Durumu",22 systemImageName: "shippingbox"23 )24 }25}Siri Integration {#siri}
App Shortcuts tanımladığında, Siri otomatik olarak intent'leri tanır. Kullanıcı "Hey Siri, [App adı] ile kahve sipariş et" dediğinde, OrderCoffeeIntent.perform() çalışır. Parametreler eksikse Siri kullanıcıya sorar.
Spotlight Donations {#spotlight}
swift
1// Son kullanılan intent'leri Spotlight'a donate et2func donateToSpotlight(order: Order) {3 let intent = ViewOrderIntent()4 intent.orderId = order.id5 let interaction = INInteraction(intent: intent, response: nil)6 interaction.donate()7}Interactive Widgets ile Intents {#widgets}
swift
1// Widget'tan intent tetikleme (iOS 17+)2struct QuickOrderWidget: Widget {3 var body: some WidgetConfiguration {4 StaticConfiguration(kind: "quickOrder", provider: Provider()) { entry in5 Button(intent: OrderCoffeeIntent(coffeeType: .latte, size: .medium)) {6 Label("Latte Sipariş", systemImage: "cup.and.saucer.fill")7 }8 }9 }10}Focus Filters {#focus-filters}
swift
1// Focus Filter - çalışma modunda sadece iş siparişlerini göster2struct WorkFocusFilter: SetFocusFilterIntent {3 static var title: LocalizedStringResource = "İş Modu Filtresi"4 5 @Parameter(title: "Sadece iş siparişleri")6 var showOnlyWorkOrders: Bool7 8 func perform() async throws -> some IntentResult {9 AppState.shared.isWorkMode = showOnlyWorkOrders10 return .result()11 }12}SiriKit → App Intents Migration {#migration}
SiriKit | App Intents |
|---|---|
INIntent subclass | AppIntent protocol |
IntentHandler | perform() metodu |
Intent Definition file | Pure Swift code |
INInteraction | Otomatik |
Custom UI Extension | SwiftUI snippet |
Best Practices {#best-practices}
- Phrase'leri doğal tut — kullanıcıların gerçekten söyleyeceği cümleler
- Error handling — Siri'ye anlamlı hata mesajları döndür
- Parametre önerileri — suggestedEntities ile hızlı seçim
- Confirmation — önemli işlemler için onay iste
- Localization — tüm string'ler LocalizedStringResource ile
Intent Return Types {#return-types}
Intent'ler farklı sonuç tipleri döndürebilir — sadece dialog değil, snippet (SwiftUI view), opened app ve daha fazlası:
swift
1// Dialog döndür - sesli yanıt2struct CheckBalanceIntent: AppIntent {3 static var title: LocalizedStringResource = "Bakiye Sorgula"4 5 func perform() async throws -> some IntentResult & ProvidesDialog {6 let balance = try await AccountService.shared.getBalance()7 return .result(dialog: "Bakiyeniz \(balance.formatted(.currency(code: "TRY")))")8 }9}10 11// Snippet döndür - SwiftUI view göster12struct ShowWeatherIntent: AppIntent {13 static var title: LocalizedStringResource = "Hava Durumu"14 15 func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView {16 let weather = try await WeatherService.shared.current()17 return .result(18 dialog: "\(weather.city) için hava durumu",19 view: WeatherSnippetView(weather: weather)20 )21 }22}23 24struct WeatherSnippetView: View {25 let weather: Weather26 27 var body: some View {28 HStack {29 Image(systemName: weather.icon)30 .font(.largeTitle)31 .foregroundStyle(weather.color)32 VStack(alignment: .leading) {33 Text(weather.city).font(.headline)34 Text("\(weather.temperature)°C - \(weather.condition)")35 .font(.subheadline)36 .foregroundStyle(.secondary)37 }38 }39 .padding()40 }41}42 43// Uygulama aç ve belirli ekrana yönlendir44struct OpenOrderDetailIntent: AppIntent {45 static var title: LocalizedStringResource = "Sipariş Detayı Aç"46 static var openAppWhenRun = true47 48 @Parameter(title: "Sipariş")49 var order: OrderEntity50 51 func perform() async throws -> some IntentResult {52 Navigator.shared.navigate(to: .orderDetail(order.id))53 return .result()54 }55}Return Type Karşılaştırma
Return Type | Kullanım | Uygulama Açılır mı? |
|---|---|---|
ProvidesDialog | Sesli/yazılı yanıt | Hayır |
ShowsSnippetView | SwiftUI view göster | Hayır |
OpensIntent | Başka intent tetikle | Duruma bağlı |
openAppWhenRun | Uygulama aç | Evet |
ReturnsValue | Shortcuts zincirine değer aktar | Hayır |
Parameterized Entity Query {#entity-query}
Entity'leri filtreleme, sıralama ve string aramayla sunmak için gelişmiş query API:
swift
1// String search + property filter desteği2struct ProductQuery: EntityStringQuery {3 // Metin araması4 func entities(matching string: String) async throws -> [ProductEntity] {5 try await ProductService.shared.search(query: string)6 }7 8 // ID ile getir9 func entities(for identifiers: [UUID]) async throws -> [ProductEntity] {10 try await ProductService.shared.getProducts(ids: identifiers)11 }12 13 // Varsayılan öneriler (Shortcuts'ta gösterilir)14 func suggestedEntities() async throws -> [ProductEntity] {15 try await ProductService.shared.getPopularProducts(limit: 10)16 }17 18 // Property-based filtering (iOS 17+)19 static var properties = QueryProperties {20 Property(\ProductEntity.$category) {21 EqualToComparator { "\($0)" }22 }23 Property(\ProductEntity.$price) {24 LessThanComparator { $0 }25 GreaterThanComparator { $0 }26 }27 }28}Confirmation Dialog {#confirmation}
Önemli işlemler için kullanıcıdan onay isteme:
swift
1struct DeleteAllOrdersIntent: AppIntent {2 static var title: LocalizedStringResource = "Tüm Siparişleri Sil"3 4 // Onay parametresi5 @Parameter(title: "Emin misiniz?")6 var confirmDeletion: Bool7 8 static var parameterSummary: some ParameterSummary {9 When(\.$confirmDeletion, .equalTo, true) {10 Summary("Tüm siparişleri sil (\(\.$confirmDeletion))")11 } otherwise: {12 Summary("Tüm siparişleri sil (\(\.$confirmDeletion))")13 }14 }15 16 func perform() async throws -> some IntentResult & ProvidesDialog {17 // requestConfirmation ile Siri'de onay diyalogu göster18 try await requestConfirmation(19 result: .result(20 dialog: "Bu işlem geri alınamaz. \(OrderService.shared.count) sipariş silinecek."21 )22 )23 24 try await OrderService.shared.deleteAll()25 return .result(dialog: "Tüm siparişler silindi.")26 }27}Shortcuts Automation Zincirleri {#automation}
Shortcuts uygulamasında intent'ler zincirlenerek güçlü automation'lar oluşturulabilir:
swift
1// Değer döndüren intent - zincirde kullanılır2struct GetTotalSpentIntent: AppIntent {3 static var title: LocalizedStringResource = "Toplam Harcama"4 5 @Parameter(title: "Dönem")6 var period: TimePeriod7 8 func perform() async throws -> some IntentResult & ReturnsValue<Double> {9 let total = try await AnalyticsService.shared.totalSpent(in: period)10 return .result(value: total)11 }12}13 14// Shortcuts zincir örneği:15// 1. GetTotalSpentIntent(period: .thisMonth) → 1250.016// 2. If total > 1000 → SendNotification("Bütçe aşımı!")17// 3. Else → ShowDialog("Bütçe kontrol altında")Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
Okuyucu Ödülü
Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var: **Kaynaklar:** - [Apple: App Intents](https://developer.apple.com/documentation/appintents) - [WWDC22: Dive into App Intents](https://developer.apple.com/videos/play/wwdc2022/10032/) - [WWDC23: Spotlight your app with App Shortcuts](https://developer.apple.com/videos/play/wwdc2023/10102/)

