介紹SiriKit
SiriKit是讓你的內(nèi)容通過Siri展示的一個(gè)框架庫。當(dāng)用戶向Siri請求特別類型的服務(wù)時(shí),系統(tǒng)就會使用Intents Extension(自定義)來支持那些服務(wù),如果需要圖形界面交互,還可以創(chuàng)建Intents Extension UI來在Siri界面上顯示自定義的UI界面。
目前為止,Siri只支持下面的6種服務(wù)類型:
- 語音或者視頻呼叫
- 信息通訊
- 支付功能
- 查找圖片
- 鍛煉
- 預(yù)約出行工具
交互過程

1 Siri語義解析,得到一個(gè)Intent,傳給Intent Extension處理
2 自定義處理對象時(shí)限相關(guān)服務(wù)域協(xié)議,resolve、confirm、handle(必須有)三個(gè)步驟某個(gè)intent。
3 返回XXXIntentResponse對象給Siri,用于回饋一個(gè)intent的響應(yīng)
Siri和Maps通過intent擴(kuò)展于你的app進(jìn)行交互。intent擴(kuò)展的入口點(diǎn)事INExtension對象,其唯一的工作就是讓Siri能夠響應(yīng)到用戶的請求。當(dāng)要實(shí)現(xiàn)一個(gè)intent擴(kuò)展時(shí),有三個(gè)類型對象是你會經(jīng)常用到的:
- 一個(gè)定義了用戶的intent以及包含Siri從用戶收集到的信息的intent對象。
- 一個(gè)自定義處理對象,你可以用來解析、確認(rèn)、處理某個(gè)intent。
- 一個(gè)數(shù)據(jù)對象,用于回饋一個(gè)intent的響應(yīng)對象。
當(dāng)有合適給你的擴(kuò)展處理的intent時(shí),Siri會向你的INExtension對象索要一個(gè)可以用來處理的這個(gè)intent的對象。
一個(gè)處理對象,可以是想要的任意類型。但它必須實(shí)現(xiàn)一些特殊的方法,以此來處理傳遞過來的intent。
每個(gè)intent的處理必須采用相關(guān)的協(xié)議。該協(xié)議的方法有三類:解析方法、確認(rèn)方法、處理方法。
你可以在這些方法里面實(shí)現(xiàn)如何處理某個(gè)intent,并且返回那些提供給Siri的數(shù)據(jù)。
下面的圖片顯示了在Siri和你的擴(kuò)展里面的處理程序?qū)ο笾械母呒墑e流。
在這個(gè)例子中,當(dāng)用戶使用出行預(yù)約服務(wù)請求一個(gè)預(yù)約時(shí),Siri創(chuàng)建一個(gè)包含出行的參數(shù)的intent對象,并將它發(fā)送到適合的擴(kuò)展。
解析處理方法分析這個(gè)intent包含的這些值是否能夠滿足乘坐值。當(dāng)所有的出行參數(shù)都得到解決,Siri詢問用戶要如何處理這個(gè)請求以及執(zhí)行任何最終的驗(yàn)證。
在確認(rèn)階段,處理程序提供了一個(gè)包含出行細(xì)節(jié)的響應(yīng)對象,Siri會將這個(gè)對象呈現(xiàn)給用戶。
如果用戶接受了這個(gè)出行預(yù)約,Siri就會要求處理程序來處理這個(gè)intent。而處理程序則進(jìn)行處理,并返回一個(gè)詳細(xì)的響應(yīng)結(jié)果
項(xiàng)目配置
為了支持SiriKit,必須先添加一個(gè)intent擴(kuò)展到你的應(yīng)用。
添加應(yīng)用擴(kuò)展:Intents Extension,假如你想自定義在Siri的界面,則勾選包含UIExtension選項(xiàng);

打開Intent Extension的info.plist,在NSExtension的NSExtensionAttributes鍵下,可以看到 IntensSupported 和IntentsRestrictedWhileLocked,分別代表著支持的Intent和鎖屏狀態(tài)下支持的Intent。而NSExtensionPrincipalClass字段定義了處理Intent的入口類(繼承于INExtension)。

解析以及處理Intents
當(dāng)Intent傳入到入口類中,首先會調(diào)用- (id)handlerForIntent:(INIntent *)intent;方法,該方法的返回值是一個(gè)實(shí)現(xiàn)了XXXIntentHandling協(xié)議的對象,也就是上文中的處理類。
每一個(gè)XXXIntentHandling協(xié)議中會定義一個(gè)必須實(shí)現(xiàn)的handle方法,一個(gè)可選的confirm方法,和若干reslove方法(依據(jù)當(dāng)前場景下Intent參數(shù)而定)。
比如Payment的INSendPaymentIntentHandling協(xié)議
| 功能 | 代碼 |
|---|---|
| 處理方法 | - handleSendPayment:completion: |
| 確認(rèn)方法 | - confirmSendPayment:completion: |
| 解析貨幣單位方法 | - resolveCurrencyAmountForSendPayment:withCompletion: |
| 解析附加語方法 | - resolveNoteForSendPayment:withCompletion: |
| 解析付款方式方法 | - resolvePaymentMethodForSendPayment:withCompletion: |
| 解析收款人方法 | - resolvePayeeForSendPayment:withCompletion: |
依照不同的場景(Intents Domains)和不同的命令,協(xié)議中的解析方法數(shù)目會變化。每一個(gè)解析方法都需要得到一個(gè)INIntentResolutionResult類型的實(shí)例,用來保存校驗(yàn)結(jié)果。
INIntentResolutionResult及其子類有不同的構(gòu)造方法生成不同類型的結(jié)果,用來指定和Siri的交互。
| 值類型 | 說明 |
|---|---|
| INIntentResolutionResult | |
| + (instancetype)needsValue; | 需要一個(gè)值,Siri會提示用戶給一個(gè)值 |
| + (instancetype)notRequired; | 不是必要的,是否給值都會過這個(gè)resolve |
| + (instancetype)unsupported; | 不支持的,Siri會提示用戶這個(gè)值不被支持 |
| INBooleanResolutionResult | |
| + (instancetype)successWithResolvedValue:(BOOL)resolvedValue; | 成功解析 |
| + (instancetype)confirmationRequiredWithValueToConfirm:(nullable NSNumber *)valueToConfirm; | Siri提示用戶確認(rèn)當(dāng)前是否是一個(gè)bool值 |
當(dāng)一個(gè)intent的所有參數(shù)都成功解析了,處理程序就會向用戶詢問是否確認(rèn)這個(gè)intent的細(xì)節(jié),并且提供一個(gè)建議響應(yīng)。當(dāng)所有參數(shù)被成功解析后,或者在不要求所有參數(shù)進(jìn)行解析,那么就認(rèn)為是解析成功。
在確認(rèn)期間,就可以執(zhí)行所有的intent參數(shù)的附加驗(yàn)證,以確保你可以使用該信息來執(zhí)行所請求的服務(wù)。如果之前的解析函數(shù)是單元測試,那么這個(gè)確認(rèn)函數(shù)就是集成測試,保證所有輸入?yún)?shù)正確。
最后一個(gè)處理intent的階段,就是執(zhí)行與這個(gè)intent相關(guān)的動作。在-handleSendPayment:completion函數(shù)中做相應(yīng)業(yè)務(wù)邏輯,需要注意的是你在Extension中做的修改也應(yīng)當(dāng)反應(yīng)到App主程序當(dāng)中,所以需要提供任務(wù)的數(shù)據(jù)給到App。SiriKit提供了一個(gè)包含intent細(xì)節(jié)(INIntent、INIntentResponse)的InInteraction對象,你可以使用userActivityInstance.interaction得到它,在App啟動時(shí)調(diào)用
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
函數(shù)處理來自Extension的數(shù)據(jù)。
自定義界面(Intent UI Extension)
上文說道,創(chuàng)建Extension的時(shí)候,可以在新建頁面勾選UI Extension選項(xiàng),創(chuàng)建一個(gè)Extension工程來展示頁面。
配置
同樣我們打開UI Extension的info.plist文件,我們能看見NSExtension鍵,其中有NSExtensionMainStoryboard
這個(gè)鍵值,用來指定入口的StoryBoard。和App不一樣的是,如果不適用StoryBoard方式,我們需要使用NSExtensionPrincipalClass這個(gè)鍵來指定入口的ViewController。
實(shí)現(xiàn)ViewController
系統(tǒng)創(chuàng)建了ViewController,加載視圖,調(diào)用viewDidLoad方法并且調(diào)用了INUIHostedViewControlling協(xié)議的configureWithInteraction:context:completion:方法,傳遞了一個(gè)交互對象,用于配置界面。 當(dāng)配置完成后,ViewController就會展示在Siri或者M(jìn)aps應(yīng)用界面的空白部分。這時(shí)會調(diào)用viewWillAppear/viewDidAppear方法。
當(dāng)視圖消失時(shí),也會調(diào)用生命周期的viewWillDisappear/viewDidDisappear方法。

關(guān)于控制器的使用,蘋果給出了幾點(diǎn)注意事項(xiàng):
切換子控制器來展示不同類型的內(nèi)容。 你的Intents UI擴(kuò)展只有一個(gè)主視圖控制器,如果你想為不同的Intents展示不同的內(nèi)容,你需要使用不同的視圖??梢栽?strong>configureWithInteraction:context:completion:這個(gè)方法里面,根據(jù)提供的intentObject來創(chuàng)建不同的子視圖。
在你的視圖控制器可用的期間,動態(tài)調(diào)整內(nèi)容。 在** viewDidAppear:方法里面才開始啟動動畫,在viewWillDisappear: **方法里面要結(jié)束動畫。
盡快的配置好你的視圖控制器,這樣Siri才能更快的展示它。 你的視圖控制器也許不會在屏幕上停留太久,所以盡量利用本地資源以及提供的INInteraction對象來配置你的設(shè)置。如果你需要從服務(wù)器拉取更多的信息,請異步完成,并在稍后再更新你的界面。
請不要在界面里面展示廣告。你可以展示你自己的品牌信息,但是你不能夠加入其它廣告。