Shortcuts
WWDC 2018 Session 216:Introduction to Siri Shortcuts
檢視更多 WWDC 18 相關文章請前往 老司機x知識小集xSwiftGG WWDC 18 專題目錄
作者:米廣,米菜雞在搬磚
本文主要介紹一些 SiriKit
的基本用法,以及如何建立 Shortcuts
(三個步驟)
Shortcuts
就是能夠讓使用者自定義一段語音 (Phase) 或識別使用者的語音短語,使用者說出這個短語,可以執行既定的邏輯。
Shortcuts
是 SiriKit
的一部分,是原有 SiriKit
API 的擴充套件, 使用者可以通過 Siri 指令,執行 App 內的一系列邏輯,Shortcuts
本身的指令需要足夠簡潔,Shortcuts
在設計時應該足夠的簡潔,能夠滿足使用者的目的,經常能被經常使用,並且易於記住。
Shortcuts
不是 SiriKit
中抽象的 Intent , 舉例來說 Intent 描述了一種使用者的抽象意圖,比如「訂電影票」,但一種具體的使用者意圖是「在最近電影院訂 3 張『侏羅紀公園2』的電影票」,Shortcut 就是指代這種具體的使用者意圖。Shortcut 最終是讓使用者可以利用 Siri 快速執行這種可重複的具體意圖
首先簡介一些 SiriKit
的基本用法
- 使用
SiriKit
需要在專案中先新建一個Intent Extension
的target
,如果需要自己定 Siri 中的互動檢視,還需要建立Intent UI
的Extension
,分別負責處理 Intent 的業務邏輯 和 Intent 的檢視;
- 新建
Intent Definition File
-
在
Intent Definition File
新建 Intent , 會自動生成對應 Intent 的類檔案, 在類檔案中,會關聯你宣告的 parameter 為類的屬性,有關這種檔案的具體用法,下文中會結合例項說明。 -
SiriKit
的核心是 Intent , 也就是一種自然語言的描述,描述了使用者的意圖;使用SiriKit
並不需要實現具體的自然語言解析,你只需要按照正常語言描述即可,說明一句話中需猜想的引數,Intent Definition
和Handler
也告訴 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 IntroducingSiriKit
和SiriKit
的文件 以及 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
,並向viewcontroller
的userActivity
屬性賦值即可完成 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 Shortcuts
的 Demo (點選下載) 來進行講解
-
這個 Demo 中的結構是,App 與 Intent 共用了一部分業務程式碼,也就是處理「湯」的一部分邏輯,這部分封裝為
SoupKit.framework
, 這樣做可以複用程式碼,因為 Intent 有單獨執行的能力,也會用到「湯」的相關邏輯。SoupChef
是 App 的 target ;SoupChefIntents
這個 target 處理了 Siri Intents 的實際 Handler;SoupChefInetntsUI 處理自定義的 Siri 響應檢視;SoupKit
包含了共用的「湯」的邏輯,具體邏輯見下圖,蘋果希望我們使用這種方式來組織我們的 App ,複用更多程式碼 -
步驟 I:Declare Shortcut
-
新建一個 Intent
-
Intent Definition File
選擇不在主專案中生成相關類,避免符號表衝突 -
在
Intent Definition File
中宣告如圖中的欄位,具體作用在圖中註明 -
編輯後在編譯對應的 target 時會自動生成對應的
$(name)Intent.swift
檔案,這個 intent 被關聯到SoupKit
中,所以編譯SoupKit
時會生成如下檔案 -
然後在 Intent Definition 中進一步宣告相關的
Response
-
編譯時會自動生成,對應的
IntentResponse
-
通過以上步驟,就完成了宣告一個 Siri Intent ,這個 Intent 描述了使用者向 Siri 說 'Order Soup' 的時候響應
-
-
步驟 Ⅱ:Donate Shortcut
-
結合訂餐這個場景, 每次在使用者訂完餐後,可以告知 Siri 一個新的 Intent,每次訂餐成功後,自己新建一個 Intent 物件,並呼叫
donate()
方法, 具體程式碼如下,這種方式 donate 後,使用者可以在設定 - Siri 中看到這個 Shortcut ,並且在 Spotlight 的推薦中也會出現這個 Shortcut -
Shortcuts
的一大新特性是使用者自定義語音,這樣的話,使用者可以使用自己喜歡的語音指令來完成訂餐操作,比如「來碗蛤蜊湯」,如果想要在 App 內讓使用者自定義語音命名一個 Shortcut,可以通過 PresentINUIAddVoiceShortcutViewController
例項來實現,具體方法如下 -
App 內喚起 新建和編輯 Shortcut 的Controller 會顯示如下效果,此時使用者可以將對應 Shortcut 自定義語音儲存到 iOS 內
-
在新版的 iOS12 除錯中,在 Developer 中開啟相關選項,在鎖屏和 spotlight 搜尋介面顯示上一次的
Shortcuts
指令,不需要一遍遍語音除錯 Siri -
設定好之後, 在手機上就可以看到這個,第一次需要使用 Siri 語音試一次,之後就可以在 Spotlight 和 鎖屏介面出現
-
在
OrderDetail Controller
中,有相關NSUserActivity
的相關資訊,只需將 iOS12 的新增的屬性賦值為了isEligibleForPrediction = true
,就可以直接 donateNSUserActivity
類的Shortcuts
, 也就是上面圖片中的 第二個選項 -
有關在 apple Watch 的 Siri 錶盤中展現相關 intents, 請參照(Session Siri
Shortcuts
on Watch Face)
-
-
步驟 Ⅲ:Donate Shortcut
- Intent 最終都需要通過
INExtension
的子類來進行回撥,最終會通過以下方法進入到你的程式碼中
- Intent 最終都需要通過
-
之後,你就可以進行 Intent 中進一步的處理, 該 Intent 實際為
OrderSoupIntent
,會包含 soup、quantity、options 等屬性,除錯時,可以直接將 Siri Intent Extension 也就是SoupChefIntents
這個 target 編譯到手機上,並選擇 Siri 為執行物件,就可以只除錯 Handler 相關邏輯,而不執行 App
除錯效果如下,有關 Intent 的 handler ,可以參考 demo 中的具體程式碼
自此完成了 Intent 的 Declare 、Donate 、Handle , 有關 Intent 的進一步應用,可以參考 Demo 、文件和 WWDC 相關 Session211 、214、217、225、228