App Intents และ Siri Shortcuts: ระบบอัตโนมัติ iOS ขั้นสูงปี 2026

คู่มือฉบับสมบูรณ์เกี่ยวกับ App Intents และ Siri Shortcuts สำหรับ iOS 18+ สร้างคำสั่ง Siri ที่กำหนดเอง รวม Apple Intelligence และทำให้แอป Swift เป็นอัตโนมัติในปี 2026

App Intents และ Siri Shortcuts สำหรับระบบอัตโนมัติ iOS ขั้นสูงด้วย Swift และ Apple Intelligence

ในปี 2026 ด้วย Apple Intelligence และเฟรมเวิร์ก App Intents แอป iOS ก้าวเข้าสู่ยุคที่เจตนาของผู้ใช้สำคัญกว่าหน้าจอกราฟิก แอปที่ไม่เปิดเผย intents จะมองไม่เห็นในระบบปฏิบัติการที่เน้น AI App Intents เป็นรากฐานที่ทำให้ Siri, Spotlight, วิดเจ็ต และ Action Button สามารถโต้ตอบกับฟังก์ชันของแอปได้

สิ่งที่บทความนี้ครอบคลุม

บทความนี้นำเสนอการสร้าง App Intents และ Siri Shortcuts สำหรับ iOS 18+ อย่างครบถ้วน ตั้งแต่แนวคิดพื้นฐานไปจนถึงการรวมกับ Apple Intelligence และ App Intent Domains

ทำความเข้าใจเฟรมเวิร์ก App Intents

เฟรมเวิร์ก App Intents ที่เปิดตัวพร้อม iOS 16 ปรับปรุงการสร้าง intents ใน Swift โดยแทนที่เฟรมเวิร์ก SiriKit Intents เดิม สถาปัตยกรรมเชิงประกาศนี้ทำให้สามารถสร้างคำสั่งที่ระบบค้นพบได้ ได้แก่ Spotlight, แอปทางลัด, Siri และ Action Button

TaskIntent.swiftswift
import AppIntents

// AppIntent แทนคำสั่งที่ผู้ใช้สามารถดำเนินการได้
struct CreateTaskIntent: AppIntent {
    // ชื่อที่แสดงในทางลัดและ Siri
    static var title: LocalizedStringResource = "สร้างงาน"

    // คำอธิบายสำหรับการเข้าถึงและคำแนะนำ
    static var description = IntentDescription(
        "สร้างงานใหม่ในแอปพลิเคชัน"
    )

    // พารามิเตอร์ที่มีการตรวจสอบอัตโนมัติ
    @Parameter(title: "ชื่องาน")
    var taskTitle: String

    // พารามิเตอร์เสริมพร้อมค่าเริ่มต้น
    @Parameter(title: "ลำดับความสำคัญ", default: .medium)
    var priority: TaskPriority

    // การดำเนินการคำสั่ง
    func perform() async throws -> some IntentResult & ReturnsValue<TaskEntity> {
        // สร้างงานผ่าน service
        let task = TaskService.shared.createTask(
            title: taskTitle,
            priority: priority
        )

        // ส่งคืน entity ที่สร้างขึ้นเพื่อทำ chaining
        return .result(value: TaskEntity(task: task))
    }
}

Intent ประกาศพารามิเตอร์ผ่าน property wrapper @Parameter ซึ่งช่วยให้ Siri สามารถถามค่าที่ขาดได้ เมธอด perform() เรียกใช้ตรรกะทางธุรกิจและส่งคืนผลลัพธ์ที่กำหนดประเภท

กำหนด App Entities สำหรับข้อมูล

App Entities แทน "คำนาม" ของแอป: วัตถุที่ intents ทำงานด้วย ทำให้ Siri เข้าใจและจัดการข้อมูลของแอปได้

TaskEntity.swiftswift
import AppIntents

// โมเดลข้อมูลภายใน
struct Task: Identifiable, Codable {
    let id: UUID
    var title: String
    var priority: TaskPriority
    var isCompleted: Bool
    var dueDate: Date?
}

// Entity ที่เปิดเผยต่อระบบ
struct TaskEntity: AppEntity {
    // ตัวระบุที่ไม่ซ้ำกันที่จำเป็น
    var id: UUID

    // คุณสมบัติที่แสดงได้
    var title: String
    var priority: TaskPriority
    var isCompleted: Bool

    // การกำหนดค่าการแสดงผลในระบบ
    static var typeDisplayRepresentation: TypeDisplayRepresentation = "งาน"

    // การแสดงผลภาพของอินสแตนซ์
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(title)",
            subtitle: "\(priority.rawValue)",
            image: .init(systemName: isCompleted ? "checkmark.circle.fill" : "circle")
        )
    }

    // Query เริ่มต้นสำหรับค้นหา entity
    static var defaultQuery = TaskEntityQuery()

    // Initializer จากโมเดลภายใน
    init(task: Task) {
        self.id = task.id
        self.title = task.title
        self.priority = task.priority
        self.isCompleted = task.isCompleted
    }
}

// Query เพื่อค้นหาและกรอง entity
struct TaskEntityQuery: EntityQuery {
    // ค้นหาตามตัวระบุ
    func entities(for identifiers: [UUID]) async throws -> [TaskEntity] {
        TaskService.shared.fetchTasks()
            .filter { identifiers.contains($0.id) }
            .map { TaskEntity(task: $0) }
    }

    // คำแนะนำที่แสดงในอินเทอร์เฟซ
    func suggestedEntities() async throws -> [TaskEntity] {
        TaskService.shared.fetchTasks()
            .filter { !$0.isCompleted }
            .prefix(5)
            .map { TaskEntity(task: $0) }
    }
}

EntityQuery กำหนดวิธีที่ระบบค้นหาและแนะนำ entity เมธอด entities(for:) และ suggestedEntities() ป้อนข้อมูลให้กับอินเทอร์เฟซ Siri และทางลัด

App Enums vs App Entities

ใช้ AppEnum สำหรับประเภทที่มีชุดค่าคงที่ (ลำดับความสำคัญ สถานะ) และ AppEntity สำหรับประเภทไดนามิกที่ผู้ใช้สร้าง (งาน บันทึก รายชื่อติดต่อ)

สร้าง App Enums สำหรับค่าคงที่

App Enums เปิดเผยประเภทแบบ enumerated ต่อระบบ ช่วยให้ Siri เสนอตัวเลือกตามบริบท

TaskPriority.swiftswift
import AppIntents

// Enum ที่เปิดเผยต่อระบบ
enum TaskPriority: String, AppEnum, Codable {
    case low
    case medium
    case high

    // ชื่อประเภทที่แสดง
    static var typeDisplayRepresentation: TypeDisplayRepresentation = "ลำดับความสำคัญ"

    // การแสดงผลของแต่ละกรณี
    static var caseDisplayRepresentations: [TaskPriority: DisplayRepresentation] = [
        .low: DisplayRepresentation(
            title: "ต่ำ",
            image: .init(systemName: "arrow.down.circle")
        ),
        .medium: DisplayRepresentation(
            title: "ปานกลาง",
            image: .init(systemName: "minus.circle")
        ),
        .high: DisplayRepresentation(
            title: "สูง",
            image: .init(systemName: "exclamationmark.circle")
        )
    ]
}

// Enum สำหรับสถานะของงาน
enum TaskStatus: String, AppEnum, Codable {
    case pending
    case inProgress
    case completed

    static var typeDisplayRepresentation: TypeDisplayRepresentation = "สถานะ"

    static var caseDisplayRepresentations: [TaskStatus: DisplayRepresentation] = [
        .pending: "รอดำเนินการ",
        .inProgress: "กำลังดำเนินการ",
        .completed: "เสร็จสิ้น"
    ]
}

การแสดงผลภาพ (ไอคอน SF Symbols) ทำให้การแสดงผลในทางลัดและคำแนะนำของ Siri สมบูรณ์ยิ่งขึ้น

ใช้งาน AppShortcutsProvider

AppShortcutsProvider เปิดเผย App Shortcuts ต่อระบบ ทำให้พร้อมใช้งานทันทีโดยไม่ต้องตั้งค่าจากผู้ใช้ ทางลัดเหล่านี้จะปรากฏใน Spotlight, Siri และ Action Button

ShortcutsProvider.swiftswift
import AppIntents

// Provider ที่ประกาศทางลัดทั้งหมดของแอป
struct TaskAppShortcutsProvider: AppShortcutsProvider {
    // สูงสุด 10 ทางลัดต่อแอปพลิเคชัน
    @AppShortcutsBuilder
    static var appShortcuts: [AppShortcut] {
        // ทางลัดสำหรับสร้างงาน
        AppShortcut(
            intent: CreateTaskIntent(),
            phrases: [
                // Placeholder .applicationName เป็นข้อบังคับ
                "สร้างงานด้วย \(.applicationName)",
                "งานใหม่ใน \(.applicationName)",
                "เพิ่มงานใน \(.applicationName)"
            ],
            shortTitle: "สร้างงาน",
            systemImageName: "plus.circle"
        )

        // ทางลัดสำหรับแสดงรายการงาน
        AppShortcut(
            intent: ListTasksIntent(),
            phrases: [
                "แสดงงานของฉันใน \(.applicationName)",
                "แสดงงานจาก \(.applicationName)",
                "งานของฉันมีอะไรบ้าง \(.applicationName)"
            ],
            shortTitle: "งานของฉัน",
            systemImageName: "list.bullet"
        )

        // ทางลัดที่มีพารามิเตอร์ไดนามิก
        AppShortcut(
            intent: CompleteTaskIntent(),
            phrases: [
                "ทำ \(\.$taskName) ใน \(.applicationName) ให้เสร็จ",
                "ทำเครื่องหมาย \(\.$taskName) เสร็จด้วย \(.applicationName)"
            ],
            shortTitle: "ทำงานให้เสร็จ",
            systemImageName: "checkmark.circle"
        )
    }
}

วลีเสียงต้องประกอบด้วย placeholder \(.applicationName) เพื่อให้ Siri ระบุแอปเป้าหมายได้ พารามิเตอร์ไดนามิกอย่าง \(\.$taskName) ช่วยให้คำสั่งตามบริบทเป็นไปได้

ข้อจำกัด 10 ทางลัด

แอปสามารถประกาศได้สูงสุด 10 App Shortcuts ควรจัดลำดับความสำคัญของคำสั่งที่ใช้บ่อยและเป็นประโยชน์ที่สุดสำหรับผู้ใช้

Intents ที่มีพารามิเตอร์ซับซ้อน

Intents สามารถรับพารามิเตอร์ที่ซับซ้อนได้ รวมถึง entity และตัวเลือกการกำหนดค่า

CompleteTaskIntent.swiftswift
import AppIntents

struct CompleteTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "ทำงานให้เสร็จ"

    static var description = IntentDescription(
        "ทำเครื่องหมายงานว่าเสร็จสิ้น"
    )

    // พารามิเตอร์ entity ที่มีการค้นหาอัตโนมัติ
    @Parameter(title: "งาน")
    var task: TaskEntity

    // พารามิเตอร์เสริมพร้อมวันที่
    @Parameter(title: "วันที่เสร็จสิ้น")
    var completionDate: Date?

    // การกำหนดค่ากล่องโต้ตอบ Siri
    static var parameterSummary: some ParameterSummary {
        Summary("ทำ \(\.$task) ให้เสร็จ") {
            \.$completionDate
        }
    }

    func perform() async throws -> some IntentResult & ProvidesDialog {
        // อัปเดตงาน
        TaskService.shared.completeTask(
            id: task.id,
            completionDate: completionDate ?? Date()
        )

        // ฟีดแบ็กเสียงสำหรับ Siri
        return .result(
            dialog: "งาน \(task.title) ถูกทำเครื่องหมายเสร็จแล้ว"
        )
    }
}

// Intent ที่ส่งคืนรายการ entity
struct ListTasksIntent: AppIntent {
    static var title: LocalizedStringResource = "แสดงรายการงาน"

    // ตัวกรองเสริม
    @Parameter(title: "สถานะ", default: nil)
    var statusFilter: TaskStatus?

    @Parameter(title: "ลำดับความสำคัญ", default: nil)
    var priorityFilter: TaskPriority?

    func perform() async throws -> some IntentResult & ReturnsValue<[TaskEntity]> {
        var tasks = TaskService.shared.fetchTasks()

        // ใช้ตัวกรอง
        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 กำหนดวิธีที่ Siri นำเสนอ intent ในระหว่างการดำเนินการด้วยเสียง โดยให้ฟีดแบ็กที่เป็นธรรมชาติ

พร้อมที่จะพิชิตการสัมภาษณ์ iOS แล้วหรือยังครับ?

ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ

การรวมกับ Apple Intelligence

iOS 18 เปิดตัว App Intent Domains ซึ่งเป็นชุด API ที่ออกแบบมาสำหรับฟังก์ชันเฉพาะ Domain เหล่านี้ทำให้ Apple Intelligence เข้าใจและดำเนินการคำสั่งได้แม่นยำยิ่งขึ้น

BookmarkDomainIntents.swiftswift
import AppIntents

// ปฏิบัติตามโดเมน Bookmarks สำหรับการรวม Apple Intelligence
struct SaveBookmarkIntent: AppIntent {
    static var title: LocalizedStringResource = "บันทึกบุ๊กมาร์ก"

    // พารามิเตอร์ URL พร้อมการตรวจสอบอัตโนมัติ
    @Parameter(title: "URL")
    var url: URL

    @Parameter(title: "ชื่อ", default: nil)
    var title: String?

    @Parameter(title: "โฟลเดอร์", default: nil)
    var folder: BookmarkFolderEntity?

    // เปิดแอปเมื่อจำเป็น
    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: "บันทึกบุ๊กมาร์กแล้ว: \(bookmark.title)"
        )
    }
}

// Intent ที่รับรู้เนื้อหาบนหน้าจอ (iOS 18.4+)
struct AnalyzeScreenContentIntent: AppIntent {
    static var title: LocalizedStringResource = "วิเคราะห์เนื้อหา"

    // เข้าถึงบริบทหน้าจอผ่าน Apple Intelligence
    @Parameter(title: "บริบท")
    var screenContext: String?

    func perform() async throws -> some IntentResult & ProvidesDialog {
        guard let context = screenContext else {
            return .result(dialog: "ไม่มีเนื้อหาให้วิเคราะห์")
        }

        // ประมวลผลเนื้อหาที่ Apple Intelligence ดึงออกมา
        let analysis = ContentAnalyzer.analyze(context)

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

โดเมนที่กำหนดไว้ล่วงหน้า (Books, Camera, Spreadsheets) ช่วยให้ Siri ตอบสนองต่อคำขอได้แม่นยำด้วยโมเดลที่ฝึกมาสำหรับงานเฉพาะเหล่านี้

คำสั่ง Siri ที่ต้องยืนยันจากผู้ใช้

สำหรับคำสั่งที่ละเอียดอ่อน ระบบสามารถขอการยืนยันก่อนดำเนินการได้

DeleteTaskIntent.swiftswift
import AppIntents

struct DeleteTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "ลบงาน"

    @Parameter(title: "งาน")
    var task: TaskEntity

    // ต้องการการยืนยันจากผู้ใช้
    static var isDiscoverable: Bool = true

    func perform() async throws -> some IntentResult & ProvidesDialog {
        // ขอการยืนยันผ่านกล่องโต้ตอบ
        try await requestConfirmation(
            result: .result(
                dialog: "ยืนยันการลบ \(task.title) หรือไม่?"
            )
        )

        // ลบหลังจากยืนยัน
        TaskService.shared.deleteTask(id: task.id)

        return .result(
            dialog: "งาน \(task.title) ถูกลบแล้ว"
        )
    }
}

// Intent ที่มีหลายขั้นตอนการสนทนา
struct ScheduleTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "กำหนดการงาน"

    @Parameter(title: "งาน")
    var task: TaskEntity

    @Parameter(title: "วันที่")
    var scheduledDate: Date

    @Parameter(title: "การแจ้งเตือน", default: true)
    var setReminder: Bool

    static var parameterSummary: some ParameterSummary {
        When(\.$setReminder, .equalTo, true) {
            Summary("กำหนด \(\.$task) เวลา \(\.$scheduledDate) พร้อมการแจ้งเตือน")
        } otherwise: {
            Summary("กำหนด \(\.$task) เวลา \(\.$scheduledDate)")
        }
    }

    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: "กำหนดงานเวลา \(formattedDate) แล้ว"
        )
    }
}

เมธอด requestConfirmation หยุดการดำเนินการชั่วคราวจนกว่าผู้ใช้จะยืนยัน ป้องกันคำสั่งที่ดำเนินการโดยไม่ได้ตั้งใจ

Intents ในวิดเจ็ตแบบโต้ตอบ

App Intents รวมเข้ากับ WidgetKit ได้อย่างเป็นธรรมชาติ เพื่อสร้างวิดเจ็ตแบบโต้ตอบบน iOS 17+

TaskWidgetIntents.swiftswift
import AppIntents
import WidgetKit

// Intent ที่ปรับให้เหมาะกับวิดเจ็ต (ดำเนินการรวดเร็ว)
struct ToggleTaskFromWidgetIntent: AppIntent {
    static var title: LocalizedStringResource = "สลับงาน"

    @Parameter(title: "ID งาน")
    var taskID: String

    init() {}

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

    // ไม่มีกล่องโต้ตอบสำหรับวิดเจ็ต
    func perform() async throws -> some IntentResult {
        guard let uuid = UUID(uuidString: taskID) else {
            return .result()
        }

        TaskService.shared.toggleCompletion(taskId: uuid)

        // รีเฟรชวิดเจ็ตทันที
        WidgetCenter.shared.reloadTimelines(ofKind: "TaskWidget")

        return .result()
    }
}

// View ของวิดเจ็ตพร้อมปุ่มโต้ตอบ
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)
    }
}

วิดเจ็ตใช้ไวยากรณ์ Button(intent:) เพื่อเชื่อมโต้ตอบเข้ากับ App Intent โดยตรงโดยไม่ต้องเปิดแอป

การกำหนดค่า Action Button

Action Button บน iPhone 15 Pro และรุ่นใหม่กว่าสามารถเรียกใช้ App Shortcuts ได้โดยตรง

ActionButtonIntent.swiftswift
import AppIntents

// Intent ที่ปรับให้เหมาะกับ Action Button
struct QuickCaptureIntent: AppIntent {
    static var title: LocalizedStringResource = "บันทึกด่วน"

    static var description = IntentDescription(
        "สร้างงานพร้อมชื่ออย่างรวดเร็ว"
    )

    // เปิดแอปเพื่อรับอินพุต
    static var openAppWhenRun: Bool = true

    func perform() async throws -> some IntentResult & OpensIntent {
        // การแจ้งเตือนเพื่อเปิดหน้าจอบันทึกด่วน
        NotificationCenter.default.post(
            name: .quickCaptureTriggered,
            object: nil
        )

        return .result(opensIntent: ShowQuickCaptureViewIntent())
    }
}

// ประกาศใน AppShortcutsProvider สำหรับ Action Button
extension TaskAppShortcutsProvider {
    @AppShortcutsBuilder
    static var appShortcuts: [AppShortcut] {
        // ... ทางลัดอื่น ๆ

        AppShortcut(
            intent: QuickCaptureIntent(),
            phrases: [
                "บันทึกด่วน \(.applicationName)",
                "บันทึกย่อด่วน \(.applicationName)"
            ],
            shortTitle: "บันทึก",
            systemImageName: "bolt.circle"
        )
    }
}

ผู้ใช้สามารถกำหนดค่า Action Button ให้เรียกใช้ทางลัดนี้ได้ผ่าน การตั้งค่า > Action Button

Macros iOS 18+

iOS 18 เปิดตัว macro @DeferredProperty และ @ComputedProperty เพื่อลด boilerplate App Intents ยังสามารถอยู่ใน Swift Packages เพื่อใช้ซ้ำข้ามแพลตฟอร์มได้

Intents ใน Swift Packages

App Intents สามารถกำหนดได้ใน Swift Packages เพื่อใช้ร่วมกันระหว่าง iOS, macOS และ watchOS

Package.swiftswift
// 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

// Intent ที่ใช้ร่วมกันข้ามแพลตฟอร์ม
public struct SharedCreateTaskIntent: AppIntent {
    public static var title: LocalizedStringResource = "สร้างงาน"

    @Parameter(title: "ชื่อ")
    public var taskTitle: String

    public init() {}

    public func perform() async throws -> some IntentResult {
        // ตรรกะที่ใช้ร่วมกัน
        await TaskRepository.shared.create(title: taskTitle)
        return .result()
    }
}

// ส่วนขยายเฉพาะแพลตฟอร์มในแอป
#if os(iOS)
extension SharedCreateTaskIntent {
    // พฤติกรรมเฉพาะ iOS
    static var openAppWhenRun: Bool = false
}
#endif

สถาปัตยกรรมนี้รักษาฐานโค้ดเดียวสำหรับ intents ในขณะที่ปรับพฤติกรรมตามแพลตฟอร์ม

ทดสอบ App Intents

App Intents สามารถทดสอบหน่วยได้เช่นเดียวกับโค้ด Swift ใด ๆ

TaskIntentTests.swiftswift
import XCTest
import AppIntents
@testable import TaskApp

final class TaskIntentTests: XCTestCase {

    override func setUp() {
        super.setUp()
        // รีเซ็ต service สำหรับการทดสอบที่แยกอิสระ
        TaskService.shared.reset()
    }

    func testCreateTaskIntent() async throws {
        // Given
        var intent = CreateTaskIntent()
        intent.taskTitle = "งานทดสอบ"
        intent.priority = .high

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

        // Then
        let tasks = TaskService.shared.fetchTasks()
        XCTAssertEqual(tasks.count, 1)
        XCTAssertEqual(tasks.first?.title, "งานทดสอบ")
        XCTAssertEqual(tasks.first?.priority, .high)
    }

    func testCompleteTaskIntent() async throws {
        // Given
        let task = TaskService.shared.createTask(
            title: "งานที่ต้องทำให้เสร็จ",
            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: "งาน 1", priority: .low)
        let task2 = TaskService.shared.createTask(title: "งาน 2", priority: .high)

        let query = TaskEntityQuery()

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

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

การทดสอบยืนยันพฤติกรรมของ intents โดยอิสระจากอินเทอร์เฟซระบบ

แนวทางปฏิบัติที่ดีที่สุดและการเพิ่มประสิทธิภาพ

หลายรูปแบบช่วยให้ App Intents มีประสิทธิภาพและประสบการณ์ผู้ใช้ที่ดีที่สุด

BestPractices.swiftswift
import AppIntents

// 1. วลีที่แปลแล้ว
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. การจัดการข้อผิดพลาดที่เหมาะสม
enum TaskIntentError: Error, CustomLocalizedStringResourceConvertible {
    case taskNotFound
    case invalidInput
    case serviceUnavailable

    var localizedStringResource: LocalizedStringResource {
        switch self {
        case .taskNotFound:
            return "ไม่พบงาน"
        case .invalidInput:
            return "ข้อมูลไม่ถูกต้อง"
        case .serviceUnavailable:
            return "บริการไม่พร้อมใช้งานชั่วคราว"
        }
    }
}

struct RobustTaskIntent: AppIntent {
    static var title: LocalizedStringResource = "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: "พบงาน: \(task.title)")
    }
}

// 3. การเพิ่มประสิทธิภาพ EntityQuery
struct OptimizedTaskQuery: EntityStringQuery {
    // การค้นหาข้อความที่ปรับปรุง
    func entities(matching string: String) async throws -> [TaskEntity] {
        // ค้นหาฝั่ง service พร้อมขีดจำกัด
        TaskService.shared.search(query: string, limit: 10)
            .map { TaskEntity(task: $0) }
    }

    // คำแนะนำที่จำกัดเพื่อประสิทธิภาพ
    func suggestedEntities() async throws -> [TaskEntity] {
        TaskService.shared.fetchRecentTasks(limit: 5)
            .map { TaskEntity(task: $0) }
    }
}

// 4. Focus Filter สำหรับโหมดสมาธิ
struct TaskFocusFilter: SetFocusFilterIntent {
    static var title: LocalizedStringResource = "กรองงาน"

    @Parameter(title: "แสดงเฉพาะลำดับความสำคัญสูง")
    var showHighPriorityOnly: Bool

    func perform() async throws -> some IntentResult {
        TaskService.shared.setFocusFilter(highPriorityOnly: showHighPriorityOnly)
        return .result()
    }
}

รูปแบบเหล่านี้รับประกันการรวมที่ราบรื่นกับระบบในขณะที่รักษาประสิทธิภาพที่ดีที่สุด

บทสรุป

App Intents และ Siri Shortcuts เปลี่ยนวิธีที่ผู้ใช้โต้ตอบกับแอป iOS ในปี 2026 ด้วย Apple Intelligence การเปิดเผย intents ไม่ใช่ทางเลือกอีกต่อไปแต่เป็นสิ่งจำเป็นในการมอบประสบการณ์ที่ทันสมัยและใช้งานง่าย

รายการตรวจสอบ App Intents iOS 18+

  • ✅ สร้าง AppIntents สำหรับคำสั่งหลักของแอป
  • ✅ กำหนด AppEntities สำหรับข้อมูลที่จัดการได้
  • ✅ ใช้ AppEnum สำหรับประเภทแบบ enumerated
  • ✅ ใช้งาน AppShortcutsProvider พร้อมวลีเสียง
  • ✅ ปฏิบัติตามขีดจำกัดสูงสุด 10 App Shortcuts
  • ✅ รวม \(.applicationName) ในทุกวลี
  • ✅ กำหนดค่า ParameterSummary สำหรับฟีดแบ็ก Siri
  • ✅ รวมโดเมน Apple Intelligence เมื่อเหมาะสม
  • ✅ ทดสอบ intents ด้วยการทดสอบหน่วย
  • ✅ แปลชื่อและคำอธิบาย

เริ่มฝึกซ้อมเลย!

ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ

แท็ก

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

แชร์

บทความที่เกี่ยวข้อง