WWDC 2018 Session 216:Introduction to Siri Shortcuts
查看更多 WWDC 18 相关文章请前往 老司机x知识小集xSwiftGG WWDC 18 专题目录
做者:米广,米菜鸡在搬砖ios
本文主要介绍一些 SiriKit
的基本用法,以及如何建立 Shortcuts
(三个步骤) Shortcuts
就是可以让用户自定义一段语音 (Phase) 或识别用户的语音短语,用户说出这个短语,能够执行既定的逻辑。 Shortcuts
是 SiriKit
的一部分,是原有 SiriKit
API 的扩展, 用户能够经过 Siri 指令,执行 App 内的一系列逻辑,Shortcuts
自己的指令须要足够简洁,Shortcuts
在设计时应该足够的简洁,可以知足用户的目的,常常能被常用,而且易于记住。 Shortcuts
不是 SiriKit
中抽象的 Intent , 举例来讲 Intent 描述了一种用户的抽象意图,好比「订电影票」,但一种具体的用户意图是「在最近电影院订 3 张『侏罗纪公园2』的电影票」,Shortcut 就是指代这种具体的用户意图。Shortcut 最终是让用户能够利用 Siri 快速执行这种可重复的具体意图swift
SiriKit
的基本用法SiriKit
须要在项目中先新建一个 Intent Extension
的 target
,若是须要本身定 Siri 中的交互视图,还须要建立 Intent UI
的 Extension
,分别负责处理 Intent 的业务逻辑 和 Intent 的视图;Intent Definition File
在 Intent Definition File
新建 Intent , 会自动生成对应 Intent 的类文件, 在类文件中,会关联你声明的 parameter 为类的属性,有关这种文件的具体用法,下文中会结合实例说明。api
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 Introducing SiriKit
和 SiriKit
的文档 以及 raywenderlich 的 SiriKit
快速入门!markdown
以调用 App 发送信息为例 ,IntentHandler
类会遵循 INSendMessageIntentHandling
协议,实现如下四个方法,对 Siri 的事件进行异步处理,每一个 block 中的 Result(主要包括一些内容矫正的方法) 或 Response(主要含有一个 NSUserActivity 的属性) 参数中包含了实际的处理app
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 复制代码
NSUserActivity
来实现,只需修改 userActivity
的新属性 isEligibleForPrediction
,并向 viewcontroller
的 userActivity
属性赋值便可完成 donateShortcuts
的三个步骤若是不熟悉 NSUserActivity
能够参考这里的文档 https://developer.apple.com/documentation/foundation/nsuseractivity )异步
在项目的 Info.plist 文件中, 声明一个新的 user activity type,例如:ide
<key>NSUserActivityTypes</key> <array> <string>com.myapp.name.my-activity-type</string> </array> 复制代码
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 了 复制代码
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 所告知的相关信息 } // 根据已知信息,跳转到用户所需页面,或恢复一些场景 } 复制代码
这里将借助苹果提供的 Siri Shortcuts
的 Demo (点击下载) 来进行讲解oop
这个 Demo 中的结构是,App 与 Intent 共用了一部分业务代码,也就是处理「汤」的一部分逻辑,这部分封装为SoupKit.framework
, 这样作能够复用代码,由于 Intent 有单独执行的能力,也会用到「汤」的相关逻辑。SoupChef
是 App 的 target ;SoupChefIntents
这个 target 处理了 Siri Intents 的实际 Handler;SoupChefInetntsUI 处理自定义的 Siri 响应视图;SoupKit
包含了共用的「汤」的逻辑,具体逻辑见下图,苹果但愿咱们使用这种方式来组织咱们的 App ,复用更多代码 spa
新建一个 Intent 设计
Intent Definition File
选择不在主项目中生成相关类,避免符号表冲突
在Intent Definition File
中声明如图中的字段,具体做用在图中注明
编辑后在编译对应的 target 时会自动生成对应的$(name)Intent.swift
文件,这个 intent 被关联到 SoupKit
中,因此编译 SoupKit
时会生成以下文件
而后在 Intent Definition 中进一步声明相关的 Response
编译时会自动生成,对应的IntentResponse
经过以上步骤,就完成了声明一个 Siri Intent ,这个 Intent 描述了用户向 Siri 说 'Order Soup' 的时候响应
结合订餐这个场景, 每次在用户订完餐后,能够告知 Siri 一个新的 Intent,每次订餐成功后,本身新建一个 Intent 对象,并调用 donate()
方法, 具体代码以下,这种方式 donate 后,用户能够在设置 - Siri 中看到这个 Shortcut ,而且在 Spotlight 的推荐中也会出现这个 Shortcut
Shortcuts
的一大新特性是用户自定义语音,这样的话,用户可使用本身喜欢的语音指令来完成订餐操做,好比「来碗蛤蜊汤」,若是想要在 App 内让用户自定义语音命名一个 Shortcut,能够经过 Present INUIAddVoiceShortcutViewController
实例来实现,具体方法以下
App 内唤起 新建和编辑 Shortcut 的Controller 会显示以下效果,此时用户能够将对应 Shortcut 自定义语音保存到 iOS 内
在新版的 iOS12 调试中,在 Developer 中开启相关选项,在锁屏和 spotlight 搜索界面显示上一次的 Shortcuts
指令,不须要一遍遍语音调试 Siri
设置好以后, 在手机上就能够看到这个,第一次须要使用 Siri 语音试一次,以后就能够在 Spotlight 和 锁屏界面出现
在OrderDetail Controller
中,有相关 NSUserActivity
的相关信息,只需将 iOS12 的新增的属性赋值为了 isEligibleForPrediction = true
,就能够直接 donate NSUserActivity
类的 Shortcuts
, 也就是上面图片中的 第二个选项
有关在 apple Watch 的 Siri 表盘中展示相关 intents, 请参照(Session Siri Shortcuts
on Watch Face)
INExtension
的子类来进行回调,最终会经过如下方法进入到你的代码中
以后,你就能够进行 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 、21四、21七、22五、228