ios 10 給我們帶來了很多驚喜的特性件炉,其中很多為開發(fā)者提供的勘究。其中一個就是SiriKit。
Sirikit提供給開發(fā)者使用了斟冕!這聽起來是個不錯的消息口糕,WWDC上也是響起了雷鳴般的掌聲。相信許多開發(fā)者和我一樣磕蛇,開始幻想了景描,Siri現(xiàn)在可以與我自己的應(yīng)用對話了,我可以寫一些好玩的功能秀撇,或者新開發(fā)一些好玩的應(yīng)用超棺。
不妙的是,WWDC在后面又說只支持下列6類應(yīng)用:
語音和視頻通話
發(fā)送消息
收款或者付款
圖片搜索
管理鍛煉
行程預(yù)約
看樣子Siri并沒有那么開放呵燕。
我的疑問就來了棠绘,SiriKit 是怎樣限制只能這幾種應(yīng)用呢?
我先來介紹一個重要的概念I(lǐng)ntents
字面翻譯過來是意圖, 意向再扭。Siri說出來的話氧苍,不會直接進(jìn)入到我們的app,而是會先生成一個NSIntent對象泛范。對應(yīng)6種應(yīng)用让虐,都有各自的Intents。例如發(fā)送消息的應(yīng)用是INSendMessageIntent罢荡,管理鍛煉是INStartWorkoutIntent, INEndWorkoutIntent等等澄干。每種Intents都有相關(guān)的屬性。
例如INSendMessageIntent
public class INSendMessageIntent : INIntent {
public init(recipients: [INPerson]?, content: String?, groupName: String?, serviceName: String?, sender: INPerson?)
// 發(fā)送目標(biāo)對象
public var recipients: [INPerson]? { get }
// 發(fā)送內(nèi)容
public var content: String? { get }
// 發(fā)送的群名稱柠傍,組名稱
public var groupName: String? { get }
// 用什么服務(wù)來發(fā)
public var serviceName: String? { get }
// 發(fā)送來源對象
@NSCopying public var sender: INPerson? { get }
}
Siri將說出的話麸俘,進(jìn)行分詞分析
1.確定app名稱, 你說的話里面要含app名稱,比如“微信發(fā)送消息給xx”惧笛。經(jīng)過我自己的實踐从媚,也不必每次都要帶上app名稱,siri會聰明的記住你上次喚醒的應(yīng)用患整,后面就不用帶上app名稱拜效,直接“發(fā)送消息給xx”就可以了
2.匹配應(yīng)用類型關(guān)鍵字,確定這些分詞是否存在關(guān)鍵字各谚,比如說發(fā)送消息應(yīng)用的關(guān)鍵字就是“發(fā)送”紧憾,管理鍛煉的應(yīng)用就是“鍛煉”
上面兩點滿足了,才可以進(jìn)入Sirikit extension
3.對號入座昌渤,看其他分詞是否能夠填充到Intent相應(yīng)的屬性中赴穗,你后面只能使用Intent提供的這些屬性,其他的分詞Siri分析不能填充屬性的,都被忽略
可見, 6中應(yīng)用都有各自的關(guān)鍵字和規(guī)定屬性般眉,SiriKit就是靠這種規(guī)范來限制應(yīng)用的了赵。
SiriKit必備的三個步驟
WWDC上講了SiriKit必備的三個步驟,這也是開發(fā)者需要實現(xiàn)的甸赃。
- Resolve階段:上面說的第三條對號入座就是這個階段柿汛,將語音中的關(guān)鍵信息提取出來并且填充INIntent中對應(yīng)的屬性。這是信息獲取階段埠对,簡單說就是“全與不全”
- Confirm階段:Resolve階段已經(jīng)把完整的信息交給了這個階段络断,這個階段就是根據(jù)自身App的邏輯判斷,這個信息是否允許執(zhí)行项玛,簡單的說就是“能與不能”貌笨,如果判定為允許,那么INIntent就會信息就會傳遞給UI展示
- handle階段: UI展示后稍计,用戶語音或手動確認(rèn)進(jìn)入handle階段,這個時候就可以將INIntent按照自己意愿去處理了裕循,處理之后的結(jié)果通過UI反饋給用戶
SiriKit extension 的創(chuàng)建
這個地方大同小異臣嚣,請允許我引用其他文章
用開發(fā)者賬號去下載Xcode8_beta版,然后升級一臺設(shè)備到ios10
創(chuàng)建一個空白項目剥哑,新增一個TARGET
如上圖所示硅则,我創(chuàng)建的Intents Extension被我命名為LXDSiriExtension。記住在創(chuàng)建好一個Extension的時候株婴,會詢問你是否激活這個擴(kuò)展怎虫,勾選是。另外還會提示你是否連同Intents UI Extension一并創(chuàng)建了困介,我們同樣選是大审。這樣我們在項目下面總共創(chuàng)建了LXDSiriExtension和LXDSiriExtensionUI兩個TARGET,這兩個文件目錄下面分別存在著一個新的info.plist文件座哩,這個文件用來設(shè)置intent事件發(fā)生時我們設(shè)置的處理類徒扶。
按圖中的層次展開,IntentsSupported和IntentsRestrictedWhileLocked分別是兩個字符串?dāng)?shù)組根穷,每一個字符串表示的是應(yīng)用擴(kuò)展處理的intent事件的類名姜骡。前者表示支持的事件類型,后者表示在非鎖屏狀態(tài)下執(zhí)行的事件類型屿良。文件默認(rèn)是workout類型的事件圈澈,在這里筆者改成了發(fā)送消息INSendMessageIntent。除此之外尘惧,NSExtensionPrincipalClass對應(yīng)的是INExtension子類類名康栈,這個類用來獲取處理intent事件的類。
SiriKit extension UI
拿發(fā)送信息應(yīng)用為例
這個是蘋果提供Sirikit的demo, 跑出來界面,用來發(fā)送信息的谅将。我們所能管轄的UI部分漾狼,就是紅色圈圈里面的內(nèi)容,其他都是系統(tǒng)的饥臂,不在我們的管轄范圍之內(nèi)逊躁。
那么這個紅色區(qū)域是用來做什么的呢,文檔上說隅熙,是來展示我們應(yīng)用的商標(biāo)的稽煤,因為這個界面各種應(yīng)用的模式都是這個樣子,用商標(biāo)來區(qū)分囚戚,讓用戶知道用的是哪個應(yīng)用酵熙。
在siriextensionUI的代碼中,主要是靠configure來自定義頁面的
// Prepare your view controller for the interaction to handle.
func configure(with interaction: INInteraction!, context: INUIHostedViewContext, completion: ((CGSize) -> Void)!) {
// Do configuration here, including preparing views and calculating a desired size for presentation.
if interaction.intent is INSendMessageIntent {
let sendMessageIntent:INSendMessageIntent = interaction.intent as! INSendMessageIntent;
// 如果有收信人就顯示紅色背景驰坊,否則顯示黑色背景
if sendMessageIntent.recipients!.count > 0 {
view.backgroundColor = UIColor.red()
} else {
view.backgroundColor = UIColor.black()
}
}
if let completion = completion {
completion(self.desiredSize)
}
}
INInteraction會包含NSIntent匾二,也就是用戶所說的話,我們可以NSIntent屬性來表現(xiàn)出不同UI表現(xiàn)
根據(jù)文檔中描述拳芙,有以下注意事項:
- 不能放廣告
- 事件察藐,不能添加任何手勢,一些有交互的控件
- 界面dissmiss不要保存數(shù)據(jù)
- 做動畫要在 DidAppear 開始舟扎,willDissAppear 結(jié)束
- UI顯示要快
SiriKit 不用 Storyboard
如果不想使用Storyboard
可以用NSExtensionPrincipalClass替換NSExtensionMainStoryboard的key分飞,value寫入vc類
Siri 返回結(jié)果
后補(bǔ)