Tüm Yazılar
KategoriiOS
Okuma Süresi
19 dk
Yayın Tarihi
...
Kelime Sayısı
1.596kelime

Kahveni hazırla - bu içerikli bir makale!

App Intents framework ile Siri, Shortcuts ve Spotlight entegrasyonu. Interactive widgets, Focus filters ve App Shortcuts ile uygulamanı akıllı yap.

App Intents ve Shortcuts: Siri Entegrasyonu Tam Rehber

"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

  1. App Intents Nedir?
  2. İlk Intent: @AppIntent
  3. Parametreler ve Entity
  4. App Shortcuts (Otomatik)
  5. Siri Integration
  6. Spotlight Donations
  7. Interactive Widgets ile Intents
  8. Focus Filters
  9. SiriKit → App Intents Migration
  10. 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 AppIntents
2 
3struct OrderCoffeeIntent: AppIntent {
4 static var title: LocalizedStringResource = "Kahve Sipariş Et"
5 static var description = IntentDescription("Favori kahvenizi sipariş edin")
6 
7 // Parametreler
8 @Parameter(title: "Kahve Tipi")
9 var coffeeType: CoffeeType
10 
11 @Parameter(title: "Boyut", default: .medium)
12 var size: CoffeeSize
13 
14 // Intent çalıştır
15 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 önerileri
21 static var parameterSummary: some ParameterSummary {
22 Summary("\(\.$size) \(\.$coffeeType) sipariş et")
23 }
24}
25 
26// Enum parameter
27enum CoffeeType: String, AppEnum {
28 case latte, cappuccino, americano, espresso
29 
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, large
41 
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 objesi
2struct ProductEntity: AppEntity {
3 var id: UUID
4 var name: String
5 var price: Decimal
6 var category: String
7 
8 static var typeDisplayRepresentation: TypeDisplayRepresentation = "Ürün"
9 var displayRepresentation: DisplayRepresentation {
10 DisplayRepresentation(title: "\(name)", subtitle: "\(price) TL")
11 }
12 
13 // Arama desteği
14 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ür
2struct 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 et
2func donateToSpotlight(order: Order) {
3 let intent = ViewOrderIntent()
4 intent.orderId = order.id
5 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 in
5 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öster
2struct WorkFocusFilter: SetFocusFilterIntent {
3 static var title: LocalizedStringResource = "İş Modu Filtresi"
4 
5 @Parameter(title: "Sadece iş siparişleri")
6 var showOnlyWorkOrders: Bool
7 
8 func perform() async throws -> some IntentResult {
9 AppState.shared.isWorkMode = showOnlyWorkOrders
10 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}

  1. Phrase'leri doğal tut — kullanıcıların gerçekten söyleyeceği cümleler
  2. Error handling — Siri'ye anlamlı hata mesajları döndür
  3. Parametre önerileri — suggestedEntities ile hızlı seçim
  4. Confirmation — önemli işlemler için onay iste
  5. 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ıt
2struct 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öster
12struct 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: Weather
26 
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önlendir
44struct OpenOrderDetailIntent: AppIntent {
45 static var title: LocalizedStringResource = "Sipariş Detayı Aç"
46 static var openAppWhenRun = true
47 
48 @Parameter(title: "Sipariş")
49 var order: OrderEntity
50 
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ği
2struct 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 getir
9 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 parametresi
5 @Parameter(title: "Emin misiniz?")
6 var confirmDeletion: Bool
7 
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öster
18 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ır
2struct GetTotalSpentIntent: AppIntent {
3 static var title: LocalizedStringResource = "Toplam Harcama"
4 
5 @Parameter(title: "Dönem")
6 var period: TimePeriod
7 
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.0
16// 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/)

Etiketler

#app-intents#siri#shortcuts#spotlight#ios#automation#widget
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz