WWDC 2018: Shortcuts 快速入門

yz06276發表於2019-03-04

Shortcuts

WWDC 2018 Session 216:Introduction to Siri Shortcuts
檢視更多 WWDC 18 相關文章請前往 老司機x知識小集xSwiftGG WWDC 18 專題目錄
作者:米廣,米菜雞在搬磚

本文主要介紹一些 SiriKit 的基本用法,以及如何建立 Shortcuts(三個步驟)
Shortcuts 就是能夠讓使用者自定義一段語音 (Phase) 或識別使用者的語音短語,使用者說出這個短語,可以執行既定的邏輯。
ShortcutsSiriKit 的一部分,是原有 SiriKit API 的擴充套件, 使用者可以通過 Siri 指令,執行 App 內的一系列邏輯,Shortcuts 本身的指令需要足夠簡潔,Shortcuts 在設計時應該足夠的簡潔,能夠滿足使用者的目的,經常能被經常使用,並且易於記住。
Shortcuts 不是 SiriKit 中抽象的 Intent , 舉例來說 Intent 描述了一種使用者的抽象意圖,比如「訂電影票」,但一種具體的使用者意圖是「在最近電影院訂 3 張『侏羅紀公園2』的電影票」,Shortcut 就是指代這種具體的使用者意圖。Shortcut 最終是讓使用者可以利用 Siri 快速執行這種可重複的具體意圖

首先簡介一些 SiriKit 的基本用法

  • 使用 SiriKit 需要在專案中先新建一個 Intent Extensiontarget,如果需要自己定 Siri 中的互動檢視,還需要建立 Intent UIExtension ,分別負責處理 Intent 的業務邏輯 和 Intent 的檢視;
新建 Siri Intents Extension
  • 新建 Intent Definition File
WWDC 2018: Shortcuts 快速入門
  • Intent Definition File 新建 Intent , 會自動生成對應 Intent 的類檔案, 在類檔案中,會關聯你宣告的 parameter 為類的屬性,有關這種檔案的具體用法,下文中會結合例項說明。

  • SiriKit 的核心是 Intent , 也就是一種自然語言的描述,描述了使用者的意圖;使用 SiriKit 並不需要實現具體的自然語言解析,你只需要按照正常語言描述即可,說明一句話中需猜想的引數, Intent DefinitionHandler 也告訴 Siri 如何來解析、處理和推測使用者意圖,以及根據上下文在合適的時機向使用者推薦這些 Intent 。Intent 的生命週期分為:Resolve - Confirm - Handle ,比如 Siri 中的發訊息這種 Intent(System Intent), Inetnt 描述了收件人、訊息內容等,同時需要在 IntentHandler 中解析和糾錯收件人和訊息內容(resolve),確認使用者的操作(confirm),之後將訊息傳送出去(handle);再比如 Clock 的計時器的 Intent,描述了使用者說「計時70分鐘」所想要設定的計時器中哪些部分是具體的變數,哪些是單位(resolve),以及如何轉化為對應計時器的響應(handle);滴滴做的 Intents ,通過語言解析出目的地(resolve) ,使用者確認價格(confirm),最終幫助使用者叫到車(handle)。SiriKit 在 iOS10 中推出,如果你對 SiriKit 不太熟悉,推薦 閱讀 WWDC2016 Session217 Introducing SiriKitSiriKit 的文件 以及 raywenderlich 的 SiriKit 快速入門!

  • 以呼叫 App 傳送資訊為例 ,IntentHandler 類會遵循 INSendMessageIntentHandling 協議,實現以下四個方法,對 Siri 的事件進行非同步處理,每個 block 中的 Result(主要包括一些內容矯正的方法) 或 Response(主要含有一個 NSUserActivity 的屬性) 引數中包含了實際的處理

        func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void)  // 處理接收人 - Resolve
        func resolveContent(for intent: INSendMessageIntent, with completion: @escaping (INStringResolutionResult) -> Void)  // 處理資訊內容 - Resolve
        func confirm(intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) // 確認的操作 - Confirm
        func handle(intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) // 傳送資訊 - Handle
    複製程式碼

基於 Shortcut 的行為來決定實現方法

  • 如果是開啟 App 特定頁面,跳轉到 App 內使用者繼續完成一些操作,在 Spotlight 結果中復現已經索引的內容,或者提供 Handff 操作,這種情況的 Shortcut 推薦使用 NSUserActivity 來實現,只需修改 userActivity 的新屬性 isEligibleForPrediction ,並向 viewcontrolleruserActivity 屬性賦值即可完成 donate
  • 如果使用者無需跳轉到 App 內,通過 Siri 語音或者自定義的 Siri 展示介面即可響應使用者需求(使用 Siri Intent Extension Target 響應),推薦使用 Intents , 當然 Intent 也可以實現跳轉到 App

建立 Shortcuts 的三個步驟

  • Declare Shortcut – 宣告 Shortcut

  • Donate Shortcut – 向 iOS 告知自己的 Shortcut

  • Handle Shortcut – 處理對應的 Shortcut 的實際響應

使用 NSUserActivity 實現 Shortcut

如果不熟悉 NSUserActivity可以參考這裡的文件 https://developer.apple.com/documentation/foundation/nsuseractivity )

  • 在專案的 Info.plist 檔案中, 宣告一個新的 user activity type,例如:

  • <key>NSUserActivityTypes</key> <array>
    <string>com.myapp.name.my-activity-type</string> </array>
    複製程式碼
  • 步驟 I:Declare Shortcut :宣告新的 NSUserActivity 如同以往, 要支援 Shortcuts 只需宣告一個新屬性 isEligibleForPrediction 為 true, 如下

  • let userActivity =  NSUserActivity(activityType: "com.myapp.name.my-activity-type")
    userActivity.isEligibleForSearch= true
    userActivity.isEligibleForPrediction = true // 新屬性,賦值為 true 後可以暴露給 `SiriKit`
    userActivity.title = "Activity的顯示標題"
    userActivity.userInfo = ["key": "value"] 
    userActivity.suggestedInvocationPhrase = "一些推薦的建議"
    
    let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
    let image = UIImage(named: "myImage")!
    attributes.thumbnailData = image.pngData()
    attributes.contentDescription = "Activity 的副標題"
    userActivity.contentAttributeSet = attributes
    
    viewController.userActivity = userActivity // 賦值之後,這條 UserActivity 就被 donate 了
    複製程式碼
  • 步驟 Ⅱ:Donate Shortcut :將新建的 NSUserActivity 物件賦值給 viewController 的 userActivity 屬性即可完成 donate,如上

  • 步驟 Ⅲ:Donate Shortcut :在Siri 喚起 App 時,在 Appdelegate 中處理通過 UserActivity 相關的資訊,如下

  • func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
        if userActivity.activityType == "com.myapp.name.my-activity-type" {
            // 匹配 activity 的種類
        }
        if interaction = userActivity.interaction {
            // 處理 Siri 所告知的相關資訊
        }
    // 根據已知資訊,跳轉到使用者所需頁面,或恢復一些場景
    }
    複製程式碼

使用 Intents 來建立 Shortcut

這裡將藉助蘋果提供的 Siri ShortcutsDemo (點選下載) 來進行講解

  • 這個 Demo 中的結構是,App 與 Intent 共用了一部分業務程式碼,也就是處理「湯」的一部分邏輯,這部分封裝為SoupKit.framework , 這樣做可以複用程式碼,因為 Intent 有單獨執行的能力,也會用到「湯」的相關邏輯。SoupChef 是 App 的 target ;SoupChefIntents 這個 target 處理了 Siri Intents 的實際 Handler;SoupChefInetntsUI 處理自定義的 Siri 響應檢視;SoupKit包含了共用的「湯」的邏輯,具體邏輯見下圖,蘋果希望我們使用這種方式來組織我們的 App ,複用更多程式碼

    WWDC 2018: Shortcuts 快速入門
  • 步驟 I:Declare Shortcut

    • 新建一個 Intent

      WWDC 2018: Shortcuts 快速入門
    • Intent Definition File 選擇不在主專案中生成相關類,避免符號表衝突

      WWDC 2018: Shortcuts 快速入門
    • Intent Definition File 中宣告如圖中的欄位,具體作用在圖中註明

      WWDC 2018: Shortcuts 快速入門
    • 編輯後在編譯對應的 target 時會自動生成對應的$(name)Intent.swift檔案,這個 intent 被關聯到 SoupKit 中,所以編譯 SoupKit 時會生成如下檔案

      WWDC 2018: Shortcuts 快速入門
    • 然後在 Intent Definition 中進一步宣告相關的 Response

      WWDC 2018: Shortcuts 快速入門
    • 編譯時會自動生成,對應的IntentResponse

      WWDC 2018: Shortcuts 快速入門
    • 通過以上步驟,就完成了宣告一個 Siri Intent ,這個 Intent 描述了使用者向 Siri 說 `Order Soup` 的時候響應

  • 步驟 Ⅱ:Donate Shortcut

    • 結合訂餐這個場景, 每次在使用者訂完餐後,可以告知 Siri 一個新的 Intent,每次訂餐成功後,自己新建一個 Intent 物件,並呼叫 donate() 方法, 具體程式碼如下,這種方式 donate 後,使用者可以在設定 – Siri 中看到這個 Shortcut ,並且在 Spotlight 的推薦中也會出現這個 Shortcut

      WWDC 2018: Shortcuts 快速入門
    • Shortcuts 的一大新特性是使用者自定義語音,這樣的話,使用者可以使用自己喜歡的語音指令來完成訂餐操作,比如「來碗蛤蜊湯」,如果想要在 App 內讓使用者自定義語音命名一個 Shortcut,可以通過 Present INUIAddVoiceShortcutViewController 例項來實現,具體方法如下

      WWDC 2018: Shortcuts 快速入門
    • App 內喚起 新建和編輯 Shortcut 的Controller 會顯示如下效果,此時使用者可以將對應 Shortcut 自定義語音儲存到 iOS 內

      WWDC 2018: Shortcuts 快速入門
      WWDC 2018: Shortcuts 快速入門
    • 在新版的 iOS12 除錯中,在 Developer 中開啟相關選項,在鎖屏和 spotlight 搜尋介面顯示上一次的 Shortcuts 指令,不需要一遍遍語音除錯 Siri

      WWDC 2018: Shortcuts 快速入門
    • 設定好之後, 在手機上就可以看到這個,第一次需要使用 Siri 語音試一次,之後就可以在 Spotlight 和 鎖屏介面出現

      WWDC 2018: Shortcuts 快速入門
    • OrderDetail Controller 中,有相關 NSUserActivity 的相關資訊,只需將 iOS12 的新增的屬性賦值為了 isEligibleForPrediction = true,就可以直接 donate NSUserActivity 類的 Shortcuts, 也就是上面圖片中的 第二個選項

    • 有關在 apple Watch 的 Siri 錶盤中展現相關 intents, 請參照(Session Siri Shortcuts on Watch Face)

  • 步驟 Ⅲ:Donate Shortcut

    • Intent 最終都需要通過INExtension 的子類來進行回撥,最終會通過以下方法進入到你的程式碼中
      WWDC 2018: Shortcuts 快速入門
  • 之後,你就可以進行 Intent 中進一步的處理, 該 Intent 實際為 OrderSoupIntent ,會包含 soup、quantity、options 等屬性,除錯時,可以直接將 Siri Intent Extension 也就是 SoupChefIntents 這個 target 編譯到手機上,並選擇 Siri 為執行物件,就可以只除錯 Handler 相關邏輯,而不執行 App

    WWDC 2018: Shortcuts 快速入門

除錯效果如下,有關 Intent 的 handler ,可以參考 demo 中的具體程式碼

WWDC 2018: Shortcuts 快速入門

自此完成了 Intent 的 Declare 、Donate 、Handle , 有關 Intent 的進一步應用,可以參考 Demo文件和 WWDC 相關 Session211 、214、217、225、228