# App Intents ve Siri Shortcuts: gelişmiş iOS otomasyonu 2026 > iOS 18+ için App Intents ve Siri Shortcuts hakkında eksiksiz rehber. Özel Siri eylemleri oluşturma, Apple Intelligence entegrasyonu ve 2026'da Swift uygulamasını otomatikleştirme. - Published: 2026-03-08 - Updated: 2026-04-29 - Author: SharpSkill - Tags: app-intents, siri-shortcuts, ios, swift, apple-intelligence - Reading time: 15 min --- 2026'da Apple Intelligence ve App Intents framework'ü ile iOS uygulamaları, kullanıcı niyetinin grafik arayüzden daha önemli olduğu bir döneme giriyor. Intent'leri açığa çıkarmayan uygulamalar, AI odaklı bir işletim sisteminde görünmez hale gelir. App Intents; Siri, Spotlight, widget'lar ve Action Button'ın uygulama işlevleriyle etkileşim kurmasını sağlayan temeli oluşturur. > **Bu makalenin kapsamı** > > Bu makale, temel kavramlardan Apple Intelligence ve App Intent Domains entegrasyonuna kadar iOS 18+ için App Intents ve Siri Shortcuts oluşturmayı eksiksiz biçimde sunar. ## App Intents framework'ünü anlamak iOS 16 ile tanıtılan App Intents framework'ü, Swift'te intent oluşturmayı modernize ederek eski SiriKit Intents framework'ünün yerini alır. Bu deklaratif mimari, sistem tarafından keşfedilebilen eylemler oluşturmayı sağlar: Spotlight, Kısayollar uygulaması, Siri ve Action Button. ```swift // TaskIntent.swift import AppIntents // Bir AppIntent, kullanıcının gerçekleştirebileceği bir eylemi temsil eder struct CreateTaskIntent: AppIntent { // Kısayollar ve Siri'de gösterilen başlık static var title: LocalizedStringResource = "Görev oluştur" // Erişilebilirlik ve öneriler için açıklama static var description = IntentDescription( "Uygulamada yeni bir görev oluşturur." ) // Otomatik doğrulamalı parametre @Parameter(title: "Görev başlığı") var taskTitle: String // Varsayılan değerli isteğe bağlı parametre @Parameter(title: "Öncelik", default: .medium) var priority: TaskPriority // Eylem yürütme func perform() async throws -> some IntentResult & ReturnsValue { // Servis aracılığıyla görev oluştur let task = TaskService.shared.createTask( title: taskTitle, priority: priority ) // Zincirleme için oluşturulan entity'yi döndür return .result(value: TaskEntity(task: task)) } } ``` Intent, parametrelerini `@Parameter` property wrapper'ı ile bildirir ve Siri'nin eksik değerleri sorabilmesini sağlar. `perform()` metodu iş mantığını yürütür ve tipli bir sonuç döndürür. ## Veriler için App Entities tanımlamak App Entities uygulamanın "isimlerini" temsil eder: intent'lerin üzerinde işlem yaptığı nesneler. Siri'nin uygulama verilerini anlamasına ve manipüle etmesine olanak tanır. ```swift // TaskEntity.swift import AppIntents // İç veri modeli struct Task: Identifiable, Codable { let id: UUID var title: String var priority: TaskPriority var isCompleted: Bool var dueDate: Date? } // Sisteme açılan entity struct TaskEntity: AppEntity { // Gerekli benzersiz tanımlayıcı var id: UUID // Görüntülenebilir özellikler var title: String var priority: TaskPriority var isCompleted: Bool // Sistemdeki gösterim yapılandırması static var typeDisplayRepresentation: TypeDisplayRepresentation = "Görev" // Örneğin görsel temsili var displayRepresentation: DisplayRepresentation { DisplayRepresentation( title: "\(title)", subtitle: "\(priority.rawValue)", image: .init(systemName: isCompleted ? "checkmark.circle.fill" : "circle") ) } // Entity arama için varsayılan sorgu static var defaultQuery = TaskEntityQuery() // İç modelden initializer init(task: Task) { self.id = task.id self.title = task.title self.priority = task.priority self.isCompleted = task.isCompleted } } // Entity arama ve filtreleme için sorgu struct TaskEntityQuery: EntityQuery { // Tanımlayıcılarla arama func entities(for identifiers: [UUID]) async throws -> [TaskEntity] { TaskService.shared.fetchTasks() .filter { identifiers.contains($0.id) } .map { TaskEntity(task: $0) } } // Arayüzde görüntülenen öneriler func suggestedEntities() async throws -> [TaskEntity] { TaskService.shared.fetchTasks() .filter { !$0.isCompleted } .prefix(5) .map { TaskEntity(task: $0) } } } ``` `EntityQuery`, sistemin entity'leri nasıl arayıp önerdiğini tanımlar. `entities(for:)` ve `suggestedEntities()` metotları Siri ve Kısayollar arayüzlerini besler. > **App Enums vs App Entities** > > Sabit değer kümesi olan tipler için (öncelik, durum) `AppEnum` kullanılmalı; kullanıcı tarafından oluşturulan dinamik tipler için (görevler, notlar, kişiler) ise `AppEntity` kullanılmalıdır. ## Sabit değerler için App Enums oluşturmak App Enums, sayısal tipleri sisteme açar ve Siri'nin bağlamsal seçenekler sunmasını sağlar. ```swift // TaskPriority.swift import AppIntents // Sisteme açılan enum enum TaskPriority: String, AppEnum, Codable { case low case medium case high // Görüntülenen tip adı static var typeDisplayRepresentation: TypeDisplayRepresentation = "Öncelik" // Her durumun temsili static var caseDisplayRepresentations: [TaskPriority: DisplayRepresentation] = [ .low: DisplayRepresentation( title: "Düşük", image: .init(systemName: "arrow.down.circle") ), .medium: DisplayRepresentation( title: "Orta", image: .init(systemName: "minus.circle") ), .high: DisplayRepresentation( title: "Yüksek", image: .init(systemName: "exclamationmark.circle") ) ] } // Görev durumu için enum enum TaskStatus: String, AppEnum, Codable { case pending case inProgress case completed static var typeDisplayRepresentation: TypeDisplayRepresentation = "Durum" static var caseDisplayRepresentations: [TaskStatus: DisplayRepresentation] = [ .pending: "Bekliyor", .inProgress: "Devam ediyor", .completed: "Tamamlandı" ] } ``` Görsel temsiller (SF Symbols ikonları) Kısayollar ve Siri önerilerindeki gösterimi zenginleştirir. ## AppShortcutsProvider uygulamak `AppShortcutsProvider`, App Shortcuts'ı sisteme açar ve kullanıcı yapılandırması olmadan anında erişilebilir hale getirir. Bu kısayollar Spotlight, Siri ve Action Button'da görünür. ```swift // ShortcutsProvider.swift import AppIntents // Tüm uygulama kısayollarını bildiren provider struct TaskAppShortcutsProvider: AppShortcutsProvider { // Uygulama başına en fazla 10 kısayol @AppShortcutsBuilder static var appShortcuts: [AppShortcut] { // Görev oluşturma kısayolu AppShortcut( intent: CreateTaskIntent(), phrases: [ // .applicationName placeholder'ı ZORUNLUDUR "\(.applicationName) ile görev oluştur", "\(.applicationName) içinde yeni görev", "\(.applicationName) uygulamasına görev ekle" ], shortTitle: "Görev oluştur", systemImageName: "plus.circle" ) // Görevleri listeleme kısayolu AppShortcut( intent: ListTasksIntent(), phrases: [ "\(.applicationName) içindeki görevlerimi göster", "\(.applicationName) görevlerini görüntüle", "\(.applicationName) görevlerim neler" ], shortTitle: "Görevlerim", systemImageName: "list.bullet" ) // Dinamik parametreli kısayol AppShortcut( intent: CompleteTaskIntent(), phrases: [ "\(.applicationName) içinde \(\.$taskName) tamamla", "\(.applicationName) ile \(\.$taskName) yapıldı olarak işaretle" ], shortTitle: "Görevi tamamla", systemImageName: "checkmark.circle" ) } } ``` Sesli ifadeler, Siri'nin hedef uygulamayı tanıyabilmesi için `\(.applicationName)` placeholder'ını içermelidir. `\(\.$taskName)` gibi dinamik parametreler bağlamsal komutlara olanak tanır. > **10 Shortcut sınırı** > > Bir uygulama en fazla 10 App Shortcuts bildirebilir. Kullanıcılar için en sık ve en yararlı eylemleri önceliklendirmek gerekir. ## Karmaşık parametreli intent'ler Intent'ler, entity'ler ve yapılandırma seçenekleri dahil karmaşık parametreleri kabul edebilir. ```swift // CompleteTaskIntent.swift import AppIntents struct CompleteTaskIntent: AppIntent { static var title: LocalizedStringResource = "Görevi tamamla" static var description = IntentDescription( "Bir görevi tamamlandı olarak işaretler." ) // Otomatik aramalı entity parametresi @Parameter(title: "Görev") var task: TaskEntity // Tarihli isteğe bağlı parametre @Parameter(title: "Tamamlanma tarihi") var completionDate: Date? // Siri diyalog yapılandırması static var parameterSummary: some ParameterSummary { Summary("\(\.$task) tamamla") { \.$completionDate } } func perform() async throws -> some IntentResult & ProvidesDialog { // Görevi güncelle TaskService.shared.completeTask( id: task.id, completionDate: completionDate ?? Date() ) // Siri için sesli geri bildirim return .result( dialog: "\(task.title) görevi tamamlandı olarak işaretlendi." ) } } // Entity listesi döndüren intent struct ListTasksIntent: AppIntent { static var title: LocalizedStringResource = "Görevleri listele" // İsteğe bağlı filtre @Parameter(title: "Durum", default: nil) var statusFilter: TaskStatus? @Parameter(title: "Öncelik", default: nil) var priorityFilter: TaskPriority? func perform() async throws -> some IntentResult & ReturnsValue<[TaskEntity]> { var tasks = TaskService.shared.fetchTasks() // Filtreleri uygula if let status = statusFilter { tasks = tasks.filter { switch status { case .completed: return $0.isCompleted case .pending, .inProgress: return !$0.isCompleted } } } if let priority = priorityFilter { tasks = tasks.filter { $0.priority == priority } } let entities = tasks.map { TaskEntity(task: $0) } return .result(value: entities) } } ``` `ParameterSummary`, sesli yürütme sırasında Siri'nin intent'i nasıl sunduğunu tanımlar ve doğal geri bildirim sağlar. ## Apple Intelligence entegrasyonu iOS 18, belirli işlevler için tasarlanmış API koleksiyonları olan App Intent Domains'i tanıtır. Bu alanlar, Apple Intelligence'ın eylemleri daha yüksek doğrulukla anlamasına ve yürütmesine olanak tanır. ```swift // BookmarkDomainIntents.swift import AppIntents // Apple Intelligence entegrasyonu için Bookmarks domain'ine uyum struct SaveBookmarkIntent: AppIntent { static var title: LocalizedStringResource = "Yer imi kaydet" // Otomatik doğrulamalı URL parametresi @Parameter(title: "URL") var url: URL @Parameter(title: "Başlık", default: nil) var title: String? @Parameter(title: "Klasör", default: nil) var folder: BookmarkFolderEntity? // Gerekirse uygulamayı aç static var openAppWhenRun: Bool = false func perform() async throws -> some IntentResult & ProvidesDialog { let bookmark = BookmarkService.shared.save( url: url, title: title, folder: folder?.id ) return .result( dialog: "Yer imi kaydedildi: \(bookmark.title)" ) } } // Ekran içeriği farkındalığı olan intent (iOS 18.4+) struct AnalyzeScreenContentIntent: AppIntent { static var title: LocalizedStringResource = "İçeriği analiz et" // Apple Intelligence aracılığıyla ekran bağlamına erişim @Parameter(title: "Bağlam") var screenContext: String? func perform() async throws -> some IntentResult & ProvidesDialog { guard let context = screenContext else { return .result(dialog: "Analiz edilecek içerik yok.") } // Apple Intelligence tarafından çıkarılan içeriği işle let analysis = ContentAnalyzer.analyze(context) return .result(dialog: analysis.summary) } } ``` Önceden tanımlanmış alanlar (Books, Camera, Spreadsheets) Siri'nin bu özel görevler üzerinde eğitilmiş modeller sayesinde isteklere doğru yanıt vermesini sağlar. ## Kullanıcı onaylı Siri eylemleri Hassas eylemler için sistem, yürütmeden önce onay isteyebilir. ```swift // DeleteTaskIntent.swift import AppIntents struct DeleteTaskIntent: AppIntent { static var title: LocalizedStringResource = "Görevi sil" @Parameter(title: "Görev") var task: TaskEntity // Kullanıcı onayı gerektirir static var isDiscoverable: Bool = true func perform() async throws -> some IntentResult & ProvidesDialog { // Diyalog ile onay iste try await requestConfirmation( result: .result( dialog: "\(task.title) silmek istediğinizden emin misiniz?" ) ) // Onay sonrası sil TaskService.shared.deleteTask(id: task.id) return .result( dialog: "\(task.title) görevi silindi." ) } } // Çoklu diyalog adımlı intent struct ScheduleTaskIntent: AppIntent { static var title: LocalizedStringResource = "Görev planla" @Parameter(title: "Görev") var task: TaskEntity @Parameter(title: "Tarih") var scheduledDate: Date @Parameter(title: "Hatırlatıcı", default: true) var setReminder: Bool static var parameterSummary: some ParameterSummary { When(\.$setReminder, .equalTo, true) { Summary("\(\.$task) için \(\.$scheduledDate) hatırlatıcı ile planla") } otherwise: { Summary("\(\.$task) için \(\.$scheduledDate) planla") } } func perform() async throws -> some IntentResult & ProvidesDialog { TaskService.shared.schedule( taskId: task.id, date: scheduledDate, reminder: setReminder ) let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium dateFormatter.timeStyle = .short let formattedDate = dateFormatter.string(from: scheduledDate) return .result( dialog: "Görev \(formattedDate) için planlandı." ) } } ``` `requestConfirmation` metodu, kullanıcı doğrulamasına kadar yürütmeyi duraklatır ve kazara eylemlere karşı koruma sağlar. ## Etkileşimli widget'larda intent'ler App Intents, iOS 17+ için etkileşimli widget'lar oluşturmak üzere WidgetKit ile doğal şekilde entegre olur. ```swift // TaskWidgetIntents.swift import AppIntents import WidgetKit // Widget için optimize edilmiş intent (hızlı yürütme) struct ToggleTaskFromWidgetIntent: AppIntent { static var title: LocalizedStringResource = "Görev durumunu değiştir" @Parameter(title: "Görev ID") var taskID: String init() {} init(taskID: UUID) { self.taskID = taskID.uuidString } // Widget'lar için diyalog yok func perform() async throws -> some IntentResult { guard let uuid = UUID(uuidString: taskID) else { return .result() } TaskService.shared.toggleCompletion(taskId: uuid) // Anında widget yenileme WidgetCenter.shared.reloadTimelines(ofKind: "TaskWidget") return .result() } } // Etkileşimli düğmeli widget görünümü import SwiftUI struct TaskWidgetView: View { let task: Task var body: some View { Button(intent: ToggleTaskFromWidgetIntent(taskID: task.id)) { HStack { Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle") .foregroundStyle(task.isCompleted ? .green : .secondary) Text(task.title) .strikethrough(task.isCompleted) } .padding() } .buttonStyle(.plain) } } ``` Widget'lar, etkileşimi uygulamayı açmadan doğrudan App Intent'e bağlamak için `Button(intent:)` sözdizimini kullanır. ## Action Button yapılandırması iPhone 15 Pro ve sonraki modellerdeki Action Button, App Shortcuts'ı doğrudan tetikleyebilir. ```swift // ActionButtonIntent.swift import AppIntents // Action Button için optimize edilmiş intent struct QuickCaptureIntent: AppIntent { static var title: LocalizedStringResource = "Hızlı yakalama" static var description = IntentDescription( "Başlığa sahip bir görevi hızla oluşturur." ) // Giriş için uygulamayı açar static var openAppWhenRun: Bool = true func perform() async throws -> some IntentResult & OpensIntent { // Hızlı yakalama ekranını açmak için bildirim NotificationCenter.default.post( name: .quickCaptureTriggered, object: nil ) return .result(opensIntent: ShowQuickCaptureViewIntent()) } } // Action Button için AppShortcutsProvider'da bildir extension TaskAppShortcutsProvider { @AppShortcutsBuilder static var appShortcuts: [AppShortcut] { // ... diğer kısayollar AppShortcut( intent: QuickCaptureIntent(), phrases: [ "\(.applicationName) hızlı yakalama", "\(.applicationName) hızlı not" ], shortTitle: "Yakala", systemImageName: "bolt.circle" ) } } ``` Kullanıcılar, Ayarlar > Action Button üzerinden bu kısayolu tetiklemek için Action Button'ı yapılandırabilir. > **iOS 18+ macro'lar** > > iOS 18, boilerplate'i azaltmak için `@DeferredProperty` ve `@ComputedProperty` macro'larını tanıtır. App Intents ayrıca platformlar arası yeniden kullanım için Swift Packages içinde bulunabilir. ## Swift Packages içinde intent'ler App Intents, iOS, macOS ve watchOS arasında paylaşım için Swift Packages içinde tanımlanabilir. ```swift // Package.swift // swift-tools-version: 5.9 import PackageDescription let package = Package( name: "TaskIntents", platforms: [ .iOS(.v17), .macOS(.v14), .watchOS(.v10) ], products: [ .library(name: "TaskIntents", targets: ["TaskIntents"]) ], dependencies: [], targets: [ .target( name: "TaskIntents", dependencies: [] ) ] ) // Sources/TaskIntents/SharedIntents.swift import AppIntents // Platformlar arası paylaşılan intent public struct SharedCreateTaskIntent: AppIntent { public static var title: LocalizedStringResource = "Görev oluştur" @Parameter(title: "Başlık") public var taskTitle: String public init() {} public func perform() async throws -> some IntentResult { // Paylaşılan mantık await TaskRepository.shared.create(title: taskTitle) return .result() } } // Uygulamada platforma özgü uzantı #if os(iOS) extension SharedCreateTaskIntent { // iOS'a özgü davranış static var openAppWhenRun: Bool = false } #endif ``` Bu mimari, intent'ler için tek bir kod tabanı tutarken davranışı platforma göre uyarlar. ## App Intents test etmek App Intents, herhangi bir Swift kodu gibi birim testlerle test edilebilir. ```swift // TaskIntentTests.swift import XCTest import AppIntents @testable import TaskApp final class TaskIntentTests: XCTestCase { override func setUp() { super.setUp() // İzole testler için servisi sıfırla TaskService.shared.reset() } func testCreateTaskIntent() async throws { // Given var intent = CreateTaskIntent() intent.taskTitle = "Test görevi" intent.priority = .high // When let result = try await intent.perform() // Then let tasks = TaskService.shared.fetchTasks() XCTAssertEqual(tasks.count, 1) XCTAssertEqual(tasks.first?.title, "Test görevi") XCTAssertEqual(tasks.first?.priority, .high) } func testCompleteTaskIntent() async throws { // Given let task = TaskService.shared.createTask( title: "Tamamlanacak görev", priority: .medium ) var intent = CompleteTaskIntent() intent.task = TaskEntity(task: task) // When _ = try await intent.perform() // Then let updatedTask = TaskService.shared.fetchTask(id: task.id) XCTAssertTrue(updatedTask?.isCompleted ?? false) } func testEntityQuery() async throws { // Given let task1 = TaskService.shared.createTask(title: "Görev 1", priority: .low) let task2 = TaskService.shared.createTask(title: "Görev 2", priority: .high) let query = TaskEntityQuery() // When let entities = try await query.entities(for: [task1.id, task2.id]) // Then XCTAssertEqual(entities.count, 2) } } ``` Testler, intent davranışını sistem arayüzünden bağımsız olarak doğrular. ## En iyi uygulamalar ve optimizasyonlar Birkaç desen, performanslı App Intents ve optimal kullanıcı deneyimi sağlar. ```swift // BestPractices.swift import AppIntents // 1. Yerelleştirilmiş ifadeler struct LocalizedTaskIntent: AppIntent { static var title: LocalizedStringResource = "task.create.title" static var description = IntentDescription( "task.create.description", categoryName: "task.category" ) @Parameter(title: "task.parameter.title") var taskTitle: String func perform() async throws -> some IntentResult { // ... return .result() } } // 2. Doğru hata yönetimi enum TaskIntentError: Error, CustomLocalizedStringResourceConvertible { case taskNotFound case invalidInput case serviceUnavailable var localizedStringResource: LocalizedStringResource { switch self { case .taskNotFound: return "Görev bulunamadı." case .invalidInput: return "Geçersiz veri." case .serviceUnavailable: return "Servis geçici olarak kullanılamıyor." } } } struct RobustTaskIntent: AppIntent { static var title: LocalizedStringResource = "Sağlam intent" @Parameter(title: "ID") var taskId: String func perform() async throws -> some IntentResult & ProvidesDialog { guard let uuid = UUID(uuidString: taskId) else { throw TaskIntentError.invalidInput } guard let task = TaskService.shared.fetchTask(id: uuid) else { throw TaskIntentError.taskNotFound } return .result(dialog: "Görev bulundu: \(task.title)") } } // 3. EntityQuery optimizasyonu struct OptimizedTaskQuery: EntityStringQuery { // Optimize edilmiş metin araması func entities(matching string: String) async throws -> [TaskEntity] { // Limitli servis tarafı arama TaskService.shared.search(query: string, limit: 10) .map { TaskEntity(task: $0) } } // Performans için sınırlı öneriler func suggestedEntities() async throws -> [TaskEntity] { TaskService.shared.fetchRecentTasks(limit: 5) .map { TaskEntity(task: $0) } } } // 4. Odak modları için Focus Filter struct TaskFocusFilter: SetFocusFilterIntent { static var title: LocalizedStringResource = "Görevleri filtrele" @Parameter(title: "Yalnızca yüksek öncelikli olanları göster") var showHighPriorityOnly: Bool func perform() async throws -> some IntentResult { TaskService.shared.setFocusFilter(highPriorityOnly: showHighPriorityOnly) return .result() } } ``` Bu desenler, optimal performans korunurken sistemle akıcı entegrasyon sağlar. ## Sonuç App Intents ve Siri Shortcuts, kullanıcıların iOS uygulamalarıyla nasıl etkileşime girdiğini dönüştürür. 2026'da Apple Intelligence ile intent'leri açığa çıkarmak artık isteğe bağlı değil, modern ve sezgisel bir deneyim sunmak için zorunludur. ### App Intents iOS 18+ kontrol listesi - ✅ Uygulamanın ana eylemleri için AppIntents oluşturulmalı - ✅ Manipüle edilebilir veriler için AppEntities tanımlanmalı - ✅ Sayısal tipler için AppEnum kullanılmalı - ✅ Sesli ifadelerle AppShortcutsProvider uygulanmalı - ✅ En fazla 10 App Shortcuts sınırına uyulmalı - ✅ Tüm ifadelere `\(.applicationName)` dahil edilmeli - ✅ Siri geri bildirimi için ParameterSummary yapılandırılmalı - ✅ Uygunsa Apple Intelligence alanları entegre edilmeli - ✅ Intent'ler birim testlerle test edilmeli - ✅ Başlıklar ve açıklamalar yerelleştirilmeli --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/ios/app-intents-siri-shortcuts-advanced-ios-automation