Swift

利用 App Intents 在 SwiftUI App 中新增捷徑與 Siri 支援

利用 App Intents 在 SwiftUI App 中新增捷徑與 Siri 支援
利用 App Intents 在 SwiftUI App 中新增捷徑與 Siri 支援
In: Swift

你是否曾經想過,如何讓 App 的功能可以直接從 iOS 內建的「捷徑」(Shortcuts) App 使用?這正是 App Intents 框架的用途。自 iOS 16 和 macOS Ventura 推出以來,這個框架已經存在兩年多,為開發者提供了一種強大的方式來定義可透過捷徑觸發的動作。藉由 App Intents,你的 App 可以無縫整合到捷徑 App、Siri,甚至是系統層級的 Spotlight 搜尋中。

在這篇教學中,我們將示範如何使用 App Intents 框架,將 App 的功能帶入捷徑,並建立一個 App Shortcut。以 Ask Me Anything App 為例,我們會一步步示範如何讓使用者直接在捷徑中提問。

本教學假設你已經熟悉我們在 Foundation Models 教學中介紹的 Ask Me Anything App。如果你還沒看過,建議先閱讀這篇教學

使用 App Intents

Ask Me Anything App 允許使用者提出問題,並透過裝置端的 LLM 回答。我們接下來要做的,就是把這個功能公開給捷徑 App 使用。要達成這件事,你只需要建立一個新的 Struct,並採用 App Intents 框架。

在 AskMeAnything 專案中建立一個名為 AskQuestionIntent 的新檔案,並將內容更新如下:

import SwiftUI
import AppIntents

struct AskQuestionIntent: AppIntent {
    static var title: LocalizedStringResource = "Ask Question"
    static var description = IntentDescription("Ask a question to get an AI-powered answer")
    
    static let supportedModes: IntentModes = .foreground
    
    @Parameter(title: "Question", description: "The question you want to ask")
    var question: String
    
    @AppStorage("incomingQuestion") var storedQuestion: String = ""
    
    init() {}
    
    init(question: String) {
        self.question = question
    }
    
    func perform() async throws -> some IntentResult {
        storedQuestion = question
        
        return .result()
    }
}

上面的程式碼定義了一個名為 AskQuestionIntent 的 struct,它是一個使用 AppIntents 框架的 App Intent。App Intent 基本上是一種讓你的 App 能夠與捷徑 App、Siri 或 Spotlight「對話」的方式。在這裡,這個 intent 的工作是讓使用者可以提出問題並取得 AI 驅動的回答。

最上方我們定義了兩個靜態屬性:titledescription。這些內容會顯示在捷徑 App 或 Siri 中,當使用者檢視這個 intent 時就會看到。

supportedModes 屬性指定這個 intent 只能在前景模式下執行,意思是當捷徑被觸發時,App 會被打開。

@Parameter 屬性包裝器用來定義使用者需要提供的輸入。在這個例子中,它是一個 question 字串。當有人使用這個捷徑時,系統會提示他輸入或說出這個問題。

@AppStorage("incomingQuestion") 屬性是一種方便的方式,能將提供的問題儲存在 UserDefaults 中,讓 App 其他部分也能存取。

最後,perform() 函式是這個 intent 實際執行任務的地方。在這個例子中,它只是將參數中的 question 存到 storedQuestion,然後回傳 .result() 告訴系統已完成。在這裡並沒有直接進行 AI 答題,而是將問題傳入 App 中,讓 App 用自己想要的方式來處理。

處理捷徑

現在捷徑已經準備好了,執行「Ask Question」捷徑會自動開啟 App。為了處理這個功能,我們需要對 ContentView 做一點小更新。

首先,宣告一個變數,用來接收捷徑提供的問題,如下所示:

@AppStorage("incomingQuestion") private var incomingQuestion: String = ""

接著,在 scroll view 上附加 onChange 修飾器:

ScrollView {

...


}
.onChange(of: incomingQuestion) { _, newQuestion in
    if !newQuestion.isEmpty {
        question = newQuestion
        incomingQuestion = ""
        
        Task {
            await generateAnswer()
        }
    }
}

在上面的程式碼中,我們在 ScrollView 上附加了 .onChange 修飾器,讓畫面能在 incomingQuestion 值更新時做出回應。在閉包內,我們會檢查是否有從捷徑收到新的問題,如果有,就觸發 generateAnswer() 方法,將問題傳送到裝置端 LLM 處理,並回傳 AI 生成的答案。

新增預先設定的捷徑

基本上,這就是建立一個能直接連接到 App 的捷徑的方式。
如果你之前探索過捷徑 App,應該會注意到許多 App 已經提供了預先設定好的捷徑。例如,行事曆 App 就內建了建立與管理事件的捷徑。

使用 App Intents 框架,將這些預先設定好的捷徑加入到你自己的 App 中非常簡單。它們可以立即在捷徑 App 中使用,或者透過 Siri 免持觸發。我們可以在先前定義的 AskQuestionIntent 基礎上,建立對應的捷徑,讓使用者更方便地使用。例如,以下示範如何定義一個「提問」捷徑:

struct AskQuestionShortcut: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: AskQuestionIntent(),
            phrases: [
                "Ask \(.applicationName) a question",
                "Ask \(.applicationName) about \(.applicationName)",
                "Get answer from \(.applicationName)",
                "Use \(.applicationName)"
            ],
            shortTitle: "Ask Question",
            systemImageName: "questionmark.bubble"
        )
    }
}

AskQuestionShortcut 採用了 AppShortcutsProvider 協議,這就是我們告訴系統我們的 App 支援哪些捷徑的方式。在裡面,我們定義了一個名為「提問」的單一捷徑,它與我們的 AskQuestionIntent 綁定。我們也提供了一組範例語句,讓使用者可能會對 Siri 說,例如「問 [App 名稱] 一個問題」或「從 [App 名稱] 獲取答案」。

最後,我們給這個捷徑設定了一個簡短的標題和系統圖示名稱,讓它在捷徑 App 中可以被視覺辨識。一旦這段程式碼就位,系統會自動註冊它,使用者就能看到捷徑已經準備好使用——不需要額外設定。

測試捷徑(Shortcuts)

要試用這個捷徑,先在模擬器或實體 iOS 裝置上編譯並執行 App。當 App 至少啟動過一次後,回到主畫面並打開捷徑 App。你現在應該可以找到我們剛建立的「提問」捷徑,隨時準備使用。

這個新捷徑不只會出現在捷徑 App 中,也能在 Spotlight 搜尋中使用。

當你執行「提問」捷徑時,它會自動提示你輸入問題。一旦你輸入問題並點擊完成,它就會打開 App 並顯示答案。

總結

在本教程中,我們探索了如何使用 App Intents 框架,將你的 App 功能給捷徑 App 和 Siri 使用。我們示範了如何建立一個 AppIntent 來處理使用者輸入、定義一個預先設定好的捷徑,並在捷徑 App 中直接進行測試。有了這個設定,使用者現在可以直接從捷徑或透過 Siri 向「Ask Me Anything」App 提問,使操作更快速、更方便。

在下一個教程中,我們將更進一步,示範如何在 Live Activity 中顯示 AI 的回答。這樣,使用者就能即時看到回應(在鎖定畫面或 Dynamic Island 上)。

作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 18 App 程式設計實戰心法》、《iOS 18 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
如何把 Swift DocC 文檔託管到 Web Server 或 GitHub
Xcode

如何把 Swift DocC 文檔託管到 Web Server 或 GitHub

Apple 在 Xcode 13 推出了文檔編譯工具 Swift DocC,讓開發者可以為專案創建漂亮的交互式文檔,我們還可以將把文檔託管在網站上。在這篇文章中,我會簡單介紹 Swift DocC,並教大家把程式碼文檔發佈到自己的網頁或 GitHub,與更多讀者共享文檔。
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。