App Intents 2.0 ve Siri Shortcuts: iOS 27 Otomasyon Rehberi

iOS 27 için App Intents 2.0 ve Siri Shortcuts hakkında eksiksiz rehber. Streaming responses, çok turlu konuşmalar, View Annotations oluşturma ve Foundation Models entegrasyonu.

Swift ve Apple Intelligence ile gelişmiş iOS otomasyonu için App Intents ve Siri Shortcuts

App Intents 2.0 ve Siri Shortcuts, iOS 27'de üçüncü taraf uygulamalarının Siri ile entegre olabilmesinin tek yolunu temsil eder. WWDC 2026'nın ardından Apple, SiriKit'i kullanımdan kaldırdı ve App Intents'i sesli etkileşim, Spotlight keşfi ve otomasyon iş akışları için zorunlu framework olarak konumlandırdı.

Bu makalenin kapsamı

Bu makale, temel kavramlardan streaming responses, çok turlu konuşmalar ve View Annotations API'ye kadar iOS 27 için App Intents ve Siri Shortcuts oluşturmayı eksiksiz biçimde sunar.

App Intents 2.0 Framework'ünü Anlamak

iOS 16 ile tanıtılan ve WWDC 2026'da 2.0 sürümüne genişletilen App Intents framework'ü, sistem tarafından keşfedilebilen eylemler oluşturmak için Swift-native, deklaratif bir framework'tür. iOS 27 dört önemli yenilik getirir: uzun süren işlemler için streaming responses, çok turlu konuşma follow-up'ları, ekran öğelerine referans vermek için View Annotations ve eğitim ifadeleri olmadan semantik anlama için App Schemas.

WWDC 2026'da Apple resmi olarak SiriKit'i kullanımdan kaldırdı ve App Intents'i Siri'nin üçüncü taraf uygulamalarla etkileşim kurabilmesinin tek yolu haline getirdi. Mevcut SiriKit kodu kullanımdan kaldırma uyarılarıyla derlenmeye devam eder, ancak Apple kaldırmadan önce iki ila üç yıllık bir destek penceresi işaret etti.

TaskIntent.swiftswift
import AppIntents

// An AppIntent represents an action users can perform
struct CreateTaskIntent: AppIntent {
    // Title displayed in Shortcuts and Siri
    static var title: LocalizedStringResource = "Create a task"

    // Description for accessibility and suggestions
    static var description = IntentDescription(
        "Creates a new task in the application."
    )

    // Parameter with automatic validation
    @Parameter(title: "Task title")
    var taskTitle: String

    // Optional parameter with default value
    @Parameter(title: "Priority", default: .medium)
    var priority: TaskPriority

    // Action execution with async/await
    func perform() async throws -> some IntentResult & ReturnsValue<TaskEntity> {
        // Create task via service
        let task = TaskService.shared.createTask(
            title: taskTitle,
            priority: priority
        )

        // Return created entity for chaining
        return .result(value: TaskEntity(task: task))
    }
}

Intent, parametrelerini @Parameter property wrapper'ı ile bildirir ve Siri'nin eksik değerleri konuşma halinde sormasını sağlar. perform() metodu iş mantığını yürütür ve tipli bir sonuç döndürür. Tip sistemi, Siri AI'ın dinamik olarak keşfettiği schema olarak işlev görür.

Uzun Süren Eylemler için Streaming Responses

App Intents 2.0, intent'lerin tamamlanana kadar beklemek yerine yürütme sırasında ilerleme bildirmesine olanak tanıyan streaming responses'ı tanıtır. Bu özellik, dosya yüklemeleri, veri senkronizasyonu veya kullanıcıların geri bildirime ihtiyaç duyduğu karmaşık hesaplamalar gibi senaryoları ele alır.

StreamingExportIntent.swiftswift
import AppIntents

struct ExportDataIntent: AppIntent {
    static var title: LocalizedStringResource = "Export data"

    @Parameter(title: "Format")
    var format: ExportFormat

    // Streaming response for progress reporting
    func perform() async throws -> some IntentResult & ProvidesDialog {
        let totalItems = DataService.shared.itemCount
        var processed = 0

        // Stream progress updates to Siri
        for item in DataService.shared.allItems {
            await exportItem(item, format: format)
            processed += 1

            // Report progress at intervals
            if processed % 100 == 0 {
                await reportProgress(
                    "Exported (processed) of (totalItems) items..."
                )
            }
        }

        return .result(
            dialog: "Export complete. (totalItems) items saved as (format.rawValue)."
        )
    }
}

Streaming responses, birkaç saniyeden uzun süren işlemler sırasında kullanıcıyı sessizlikte bırakmak yerine etkileşimi sürdürerek doğal geri bildirim sağlar.

Çok Turlu Konuşma Follow-up'ları

Çok turlu konuşmalar, Siri'nin açıklayıcı sorular sormasına ve tek bir oturum içinde etkileşimi sürdürmesine olanak tanır. Bu özellik, App Intents'i tek seferlik komutlardan konuşma iş akışlarına dönüştürür.

ConversationalTaskIntent.swiftswift
import AppIntents

struct SmartTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "Create smart task"

    @Parameter(title: "Task title")
    var taskTitle: String?

    @Parameter(title: "Priority")
    var priority: TaskPriority?

    @Parameter(title: "Due date")
    var dueDate: Date?

    // Multi-turn conversation flow
    func perform() async throws -> some IntentResult & ProvidesDialog {
        // Request missing parameters conversationally
        let title = try await taskTitle ?? requestValue(
            for: .,
            dialog: "What should the task be called?"
        )

        let taskPriority = try await priority ?? requestValue(
            for: .,
            dialog: "What priority level?"
        )

        // Optional follow-up
        let date: Date?
        if try await requestConfirmation(
            result: .result(dialog: "Should this task have a due date?")
        ) {
            date = try await requestValue(
                for: .,
                dialog: "When is it due?"
            )
        } else {
            date = nil
        }

        let task = TaskService.shared.createTask(
            title: title,
            priority: taskPriority,
            dueDate: date
        )

        return .result(
            dialog: "Created '(task.title)' with (taskPriority.rawValue) priority."
        )
    }
}

requestValue(for:dialog:) metodu, Siri kullanıcının yanıtını alana kadar yürütmeyi duraklatır ve tüm parametreleri önceden gerektirmek yerine doğal bir alışveriş oluşturur.

Ekran Referansları için View Annotations API

iOS 27'de yeni olan View Annotations API, kullanıcıların "bu fotoğraf", "üçüncüsü" veya "o mesaj" gibi ifadeler kullanarak UI öğelerine doğrudan Siri komutlarında başvurmasını sağlar. Bu özellik, SwiftUI görünümlerinin semantik bilgilerle işaretlenmesini gerektirir.

AnnotatedPhotoView.swiftswift
import SwiftUI
import AppIntents

struct PhotoGridView: View {
    let photos: [Photo]

    var body: some View {
        LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))]) {
            ForEach(photos) { photo in
                PhotoThumbnail(photo: photo)
                    // Annotate view for Siri reference
                    .appIntentAnnotation(
                        entity: PhotoEntity(photo: photo),
                        label: photo.title
                    )
            }
        }
    }
}

// Intent that accepts view-referenced entities
struct SharePhotoIntent: AppIntent {
    static var title: LocalizedStringResource = "Share photo"

    // Parameter resolved from on-screen annotation
    @Parameter(title: "Photo", supportsViewAnnotation: true)
    var photo: PhotoEntity

    func perform() async throws -> some IntentResult & ProvidesDialog {
        await ShareService.share(photo.id)
        return .result(dialog: "Photo shared.")
    }
}

Kullanıcı grid'i görüntülerken "bu fotoğrafı paylaş" dediğinde, Siri annotation aracılığıyla "bu" ifadesini o anda odaklanılan veya son dokunulan PhotoEntity'ye çözümler. Bu, öğeleri sözlü olarak tanımlama zahmetini ortadan kaldırır.

Cihaz uyumluluğu

View Annotations iOS 27 gerektirir, ancak App Intents katmanının kendisi iPhone 11 ve sonraki modeller dahil her iOS 27 cihazında çalışır. Ekran farkındalığı gibi Apple Intelligence özellikleri iPhone 15 Pro veya sonraki modelleri gerektirir.

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, aramasına ve manipüle etmesine olanak tanır. Etkili entity'ler oluşturmak, intent odaklı uygulamalardaki SwiftUI state yönetimi kalıpları için önemlidir.

TaskEntity.swiftswift
import AppIntents

// Internal data model
struct Task: Identifiable, Codable {
    let id: UUID
    var title: String
    var priority: TaskPriority
    var isCompleted: Bool
    var dueDate: Date?
}

// Entity exposed to the system
struct TaskEntity: AppEntity {
    // Required unique identifier
    var id: UUID

    // Displayable properties
    var title: String
    var priority: TaskPriority
    var isCompleted: Bool

    // Display configuration in the system
    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Task"

    // Visual representation of the instance
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "(title)",
            subtitle: "(priority.rawValue)",
            image: .init(systemName: isCompleted ? "checkmark.circle.fill" : "circle")
        )
    }

    // Default query for searching entities
    static var defaultQuery = TaskEntityQuery()

    // Initializer from internal model
    init(task: Task) {
        self.id = task.id
        self.title = task.title
        self.priority = task.priority
        self.isCompleted = task.isCompleted
    }
}

// Optimized entity query with search
struct TaskEntityQuery: EntityStringQuery {
    // Text search with service-side filtering
    func entities(matching string: String) async throws -> [TaskEntity] {
        TaskService.shared.search(query: string, limit: 10)
            .map { TaskEntity(task: /bin/bash) }
    }

    // Search by identifiers
    func entities(for identifiers: [UUID]) async throws -> [TaskEntity] {
        TaskService.shared.fetchTasks()
            .filter { identifiers.contains(/bin/bash.id) }
            .map { TaskEntity(task: /bin/bash) }
    }

    // Limited suggestions for performance
    func suggestedEntities() async throws -> [TaskEntity] {
        TaskService.shared.fetchRecentTasks(limit: 5)
            .map { TaskEntity(task: /bin/bash) }
    }
}

EntityStringQuery protokolü metin arama özelliği ekler ve Siri'nin entity'leri isme göre bulmasını sağlar. suggestedEntities() metodu Siri ve Kısayollar arayüzlerini ilgili seçeneklerle besler.

Sabit değerler için AppEnum kullanın

Sabit değer kümesi olan tipler için (öncelik, durum) AppEnum, kullanıcı tarafından oluşturulan dinamik tipler için (görevler, notlar, kişiler) AppEntity kullanılmalıdır. Bunları karıştırmak gereksiz karmaşıklığa neden olur.

Sabit Değerler için App Enums Oluşturmak

App Enums, sayısal tipleri sisteme açar ve Siri'nin görsel temsillerle bağlamsal seçenekler sunmasını sağlar.

TaskPriority.swiftswift
import AppIntents

// Enum exposed to the system
enum TaskPriority: String, AppEnum, Codable {
    case low
    case medium
    case high

    // Type name displayed
    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Priority"

    // Representation of each case
    static var caseDisplayRepresentations: [TaskPriority: DisplayRepresentation] = [
        .low: DisplayRepresentation(
            title: "Low",
            image: .init(systemName: "arrow.down.circle")
        ),
        .medium: DisplayRepresentation(
            title: "Medium",
            image: .init(systemName: "minus.circle")
        ),
        .high: DisplayRepresentation(
            title: "High",
            image: .init(systemName: "exclamationmark.circle")
        )
    ]
}

SF Symbols ikonları, Kısayollar ve Siri önerilerindeki görünümü zenginleştirerek seçimi sözlü tanımlamalardan daha hızlı hale getirir.

iOS mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

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, Action Button ve yeni Siri AI agentic iş akışlarında görünür.

ShortcutsProvider.swiftswift
import AppIntents

// Provider declaring all app shortcuts
struct TaskAppShortcutsProvider: AppShortcutsProvider {
    // Maximum 10 shortcuts per application
    @AppShortcutsBuilder
    static var appShortcuts: [AppShortcut] {
        // Shortcut to create a task
        AppShortcut(
            intent: CreateTaskIntent(),
            phrases: [
                // The .applicationName placeholder is REQUIRED
                "Create a task with (.applicationName)",
                "New task in (.applicationName)",
                "Add a task to (.applicationName)"
            ],
            shortTitle: "Create Task",
            systemImageName: "plus.circle"
        )

        // Shortcut with dynamic parameter
        AppShortcut(
            intent: CompleteTaskIntent(),
            phrases: [
                "Complete (.) in (.applicationName)",
                "Mark (.) as done with (.applicationName)"
            ],
            shortTitle: "Complete Task",
            systemImageName: "checkmark.circle"
        )

        // Shortcut for smart conversational intent
        AppShortcut(
            intent: SmartTaskIntent(),
            phrases: [
                "Quick task (.applicationName)",
                "Remind me (.applicationName)"
            ],
            shortTitle: "Smart Task",
            systemImageName: "brain"
        )
    }
}

Sesli ifadeler, Siri'nin hedef uygulamayı tanıyabilmesi için (.applicationName) placeholder'ını içermelidir. (.) gibi dinamik parametreler bağlamsal komutlara olanak tanır.

Etkileşimli Widget'larda Intent'ler

App Intents, etkileşimli widget'lar oluşturmak için WidgetKit ile entegre olur. SwiftUI navigasyon kalıplarını anlamak, widget'tan uygulamaya geçişler oluştururken yardımcı olur.

TaskWidgetIntents.swiftswift
import AppIntents
import WidgetKit

// Widget-optimized intent (fast execution)
struct ToggleTaskFromWidgetIntent: AppIntent {
    static var title: LocalizedStringResource = "Toggle task"

    @Parameter(title: "Task ID")
    var taskID: String

    init() {}

    init(taskID: UUID) {
        self.taskID = taskID.uuidString
    }

    // No dialog for widgets
    func perform() async throws -> some IntentResult {
        guard let uuid = UUID(uuidString: taskID) else {
            return .result()
        }

        TaskService.shared.toggleCompletion(taskId: uuid)

        // Immediate widget refresh
        WidgetCenter.shared.reloadTimelines(ofKind: "TaskWidget")

        return .result()
    }
}

// Widget view with interactive button
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.

Foundation Models Framework Entegrasyonu

iOS 27, cihaz üzerinde LLM çıkarımını mümkün kılan Foundation Models framework'ü tanıtır. Foundation Models'in doğrudan Siri entegrasyonu olmasa da, uygulamalar doğal dil işleme veya yanıt üretimi için App Intents içinde kullanabilir.

AIAssistedIntent.swiftswift
import AppIntents
import FoundationModels

struct SummarizeNotesIntent: AppIntent {
    static var title: LocalizedStringResource = "Summarize notes"

    @Parameter(title: "Topic")
    var topic: String

    func perform() async throws -> some IntentResult & ProvidesDialog {
        let notes = NoteService.shared.fetchNotes(matching: topic)
        let content = notes.map(.content).joined(separator: "

")

        // Use Foundation Models for on-device summarization
        let model = LanguageModel.default
        let summary = try await model.generate(
            prompt: "Summarize these notes in 2 sentences: (content)",
            maxTokens: 100
        )

        return .result(dialog: IntentDialog(summary))
    }
}

Foundation Models, istek başına sıfır maliyet ile cihaz üzerinde saniyede yaklaşık 30 token hızında çalışır. Framework, cihaz üzerinde işleme için iPhone 15 Pro veya iPhone 16 ve sonraki modelleri gerektirir.

SiriKit'ten App Intents'e Geçiş

Hala SiriKit kullanan uygulamalar için geçiş yapılandırılmış bir süreci takip eder. Xcode 27, Widget yapılandırmaları için "Convert to App Intent" aracı sağlar, ancak özel handler'lar manuel yeniden yazım gerektirir.

swift
// Before: SiriKit Intent Handler
class CreateTaskIntentHandler: NSObject, CreateTaskIntentHandling {
    func handle(intent: CreateTaskIntent) async -> CreateTaskIntentResponse {
        guard let title = intent.taskTitle else {
            return CreateTaskIntentResponse(code: .failure, userActivity: nil)
        }

        let task = TaskService.shared.createTask(title: title)
        return CreateTaskIntentResponse.success(task: task)
    }
}

// After: App Intent (iOS 27)
struct CreateTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "Create a task"

    @Parameter(title: "Task title")
    var taskTitle: String

    func perform() async throws -> some IntentResult & ReturnsValue<TaskEntity> {
        let task = TaskService.shared.createTask(title: taskTitle)
        return .result(value: TaskEntity(task: task))
    }
}

Geçiş, .intentdefinition dosyalarını ve Intent Extension target'larını ortadan kaldırır. Tüm intent mantığı Swift struct'ları olarak ana uygulama target'ına taşınır.

App Intents Test Etmek

AppIntentsTesting framework'ü, intent'leri mock'lar olmadan gerçek Siri, Kısayollar ve Spotlight altyapısı aracılığıyla doğrular.

TaskIntentTests.swiftswift
import XCTest
import AppIntentsTesting
@testable import TaskApp

final class TaskIntentTests: XCTestCase {

    override func setUp() {
        super.setUp()
        TaskService.shared.reset()
    }

    func testCreateTaskIntent() async throws {
        // Given
        var intent = CreateTaskIntent()
        intent.taskTitle = "Test Task"
        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 Task")
        XCTAssertEqual(tasks.first?.priority, .high)
    }

    func testEntityQuery() async throws {
        // Given
        let task1 = TaskService.shared.createTask(title: "Task 1", priority: .low)
        let task2 = TaskService.shared.createTask(title: "Task 2", priority: .high)

        let query = TaskEntityQuery()

        // When
        let entities = try await query.entities(for: [task1.id, task2.id])

        // Then
        XCTAssertEqual(entities.count, 2)
    }

    func testStreamingIntent() async throws {
        // Given
        var intent = ExportDataIntent()
        intent.format = .json

        // When
        let result = try await intent.perform()

        // Then: verify completion dialog
        XCTAssertNotNil(result)
    }
}

Testler, dağıtımdan önce regresyonları yakalayarak sistem arayüzünden bağımsız olarak intent davranışını doğrular.

Kaynaklar

App Intents iOS 27 Uygulama Kontrol Listesi

iOS 27'yi hedefleyen uygulamalar için App Intents artık isteğe bağlı değildir. Siri AI, uygulamalar arasında çok adımlı eylemler oluşturur ve yayınlanmış intent'leri olmayan uygulamalar bu agentic iş akışlarından hariç tutulur.

  • Ana uygulama eylemleri için AppIntents oluşturun
  • Manipüle edilebilir veriler için AppEntities tanımlayın
  • Sayısal tipler için AppEnum kullanın
  • Sesli ifadelerle AppShortcutsProvider uygulayın
  • En fazla 10 App Shortcuts sınırına uyun
  • Tüm ifadelere (.applicationName) dahil edin
  • Ekran referansları için SwiftUI görünümlerine View Annotations ekleyin
  • Uzun süren işlemler için streaming responses uygulayın
  • Karmaşık iş akışları için çok turlu konuşmaları destekleyin
  • Kullanımdan kaldırma penceresi kapanmadan önce SiriKit'ten geçiş yapın
  • Intent'leri AppIntentsTesting framework'ü ile test edin
  • Başlıkları ve açıklamaları yerelleştirin

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Günün meydan okuması

iOS kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

20 Ağustos 2026 tarihinde güncellendi

Etiketler

#app-intents
#siri-shortcuts
#ios
#swift
#apple-intelligence

Paylaş

İlgili makaleler