“ Hey Siri…”和其他重要人物– Cory D. Wiles –中
“嘿Siri …”
到目前为止,我的主要工作之一就是将对Siri的支持添加到“有意义的他人”中。 自发布以来,以及iOS中对SiriKit的后续更新以来,开发人员能够利用这项技术向其应用程序添加全新维度的能力一直是我想要冒险的领域。
为了在您的应用程序中利用Siri,它必须属于一个Intent域 。
SiriKit定义了用户可以发出的请求类型(称为意图)。 相关的意图被分组到域中,以明确您在应用程序中可能支持的意图。 例如,邮件域具有发送邮件,搜索邮件以及将邮件标记为已读或未读的意图。
资源
Significan Other使用INMessaging域。 在INMessaging域中,由INMessagesDomainHandling
协议定义了三个可能的处理程序。
- INSendMessageIntent :撰写邮件并将其发送给一个或多个其他收件人
- INSearchForMessagesIntent :根据查询参数搜索消息
- INSetMessageAttributeIntent :请求修改消息。 即标记一条消息为已读。
我只需要对INSendMessageIntent
支持,因为您不能搜索消息并将消息标记为已阅读并不是我已经实现的功能。
Siri设置
创建了Intent Extension和Intent UI目标之后,我决定着手定制Siri UI。 虽然可能会为您的扩展程序创建自定义的UI,以替换默认界面,但我需要做一个“简单”的事情……删除“ To:”字段。 不需要它是因为您只有一个重要的其他。 少即是多 。
为此以及其他定制任务的主要工作是:
optional func configureView(for parameters: Set,
of interaction: INInteraction,
interactiveBehavior: INUIInteractiveBehavior,
context: INUIHostedViewContext,
completion: @escaping (Bool, Set, CGSize) -> Void)
资源
需要实现两点逻辑。 首先,如上所述,删除“收件人:”字段,其次我需要确保内容大小适合消息的宽度和高度。
每个参数都会多次调用configureView...
方法。
Siri或Maps呈现的每个界面都包含来自原始意图对象或您的响应的信息。 在构造接口之前,SiriKit将从打算显示的那些对象中构建属性列表。 例如,在显示有关已预订的旅程的信息时,SiriKit可能希望显示响应对象中的估计接送时间,接送位置以及驾驶员的姓名和图片。 它将每个属性包装在一个INParameter对象中,您可以使用该对象稍后检索该属性的值。
通过检查参数,内容/收件人,我可以进行自定义。
let recipients: INParameter = INParameter(for: INSendMessageIntent.self,
keyPath: #keyPath(INSendMessageIntent.recipients))
let content: INParameter = INParameter(for: INSendMessageIntent.self,
keyPath: #keyPath(INSendMessageIntent.content))
if parameters == [recipients] {
if #available(iOS 12.0, *) {
completion(true, parameters, .zero)
} else {
completion(true, parameters, self.minimumSize)
}
} else if parameters == [content] {
if #available(iOS 12.0, *) {
completion(false, parameters, self.desiredSize)
} else {
completion(true, parameters, .zero)
}
} else {
completion(false, [], .zero)
}
全面披露
上面的代码段是95%的逻辑和5%的反复试验。 文档指出完成块参数指示是否配置视图控制器的是/否。 指定 true
表示您的自定义界面已准备好显示。 指定 false
将显示指定参数的默认UI。 但是,此行为在iOS 12和iOS 11上均不起作用。我花了几个小时试图找出差异,但无济于事。 我不确定这是否是iOS 11和/或12中的错误。错误报告即将发布。
显示自定义项的最后一部分是符合INUIHostedViewSiriProviding
。
在用于在Intents UI扩展中呈现自定义内容的视图控制器中实现此协议。 Siri支持在显示位置时替换其地图界面,或在显示消息的收件人和内容时替换其消息界面。 该协议及其属性的实现是可选的。
资源
extension IntentViewController: INUIHostedViewSiriProviding {
// Public (properties)
var displaysMessage: Bool {
return true
}
}
应用程序组/ KVS商店/ CloudKit
在Intent和Intent UI中完成UI和基本协议实现后,就该处理业务逻辑了。 我的策略是利用
public func handle(intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void)
我认为这将称为主持人代表的
func application(_ application: UIApplication,
handle intent: INIntent,
completionHandler: @escaping (INIntentResponse) -> Void)
不幸的是,只有锻炼意图才能获得该功能。 尽管这不是理想的选择,但我仍然能够使用众多框架,将应用程序的功能拆分为多个模型和各种业务逻辑。 一旦CloudKit和应用程序组终止,我必须确保将来自主机应用程序的相同标识符添加到新目标中,否则我将无法访问相同的数据源。
更多来
最初推出Siri支持使我感到非常兴奋。 尽可能轻松地将您的安全/私人消息共享给您的重要他人。