Confirm阶段。在上一个阶段通过handler(for intent:)返回了处理intent的对象,此阶段会依次调用confirm打头的实例方法来判断Siri填充的信息是否完成。匹配的判断结果包括Exactly one match、Two or more matches以及No match三种情况。这个过程中可以让Siri向用户征求更具体的参数信息
Resolve阶段
这个阶段需要我们找到消息的具体接收者。在这个过程中,可能会出现三种情况:Exactly one match、Two or more matches以及No matches,对于这三种情况的处理分别如下:
func resolveRecipients(forSendMessage intent: INSendMessageIntent, with completion: ([INPersonResolutionResult]) -> Void) {
if let recipients = intent.recipients {
var resolutionResults = [INPersonResolutionResult]()
for recipient in recipients {
let matches = LXDAccount.share().contact(matchingName: recipient.displayName)
switch matches.count {
case 2...Int.max: //两个或更多匹配结果
let disambiguations = matches.map { $0.inPerson() }
resolutionResults.append(INPersonResolutionResult.disambiguation(with: disambiguations))
break
case 1: //一个匹配结果
let recipient = matches[0].inPerson()
resolutionResults.append(INPersonResolutionResult.success(with: recipient))
break
case 0: //无匹配结果
resolutionResults.append(INPersonResolutionResult.unsupported(with: .none))
break
default:
break
}
}
completion(resolutionResults)
} else {
//未从用户语音中提取到信息,需要向用户征询更多关键信息
completion([INPersonResolutionResult.needsValue()])
}
}
上面的代码用来确认出消息中的我的家人们指代的是哪些人,其中每个联系人最终用一个INPerson的对象来表示。接着我们需要匹配消息的内容:
func resolveContent(forSendMessage intent: INSendMessageIntent, with completion: (INStringResolutionResult) -> Void) {
if let text = intent.content where !text.isEmpty {
completion(INStringResolutionResult.success(with: text))
} else {
//向用户征询发送的消息内容
completion(INStringResolutionResult.needsValue())
}
}
在匹配完消息接收者跟消息内容之后,对于intent事件的处理就会进入第二阶段Confirm确认值是否正确
Confirm阶段
在这个阶段intent对象本身的信息预计是已经完成填充的,我们通过获取这些填充值来判断是否符合我们的要求。同时在这个阶段,Siri会尝试唤醒应用来准备完成最后的处理操作。前面说了为了保证在应用和应用拓展之间能够进行通信,最好使用frameworks的方式来标记应用是否被启动,再进行相应操作。
func confirm(sendMessage intent: INSendMessageIntent, completion: (INSendMessageIntentResponse) -> Void) {
/// let content = intent.content
/// let recipients = intent.recipients
/// do or judge in content & recipients
completion(INSendMessageIntentResponse(code: .success, userActivity: nil))
/// Launch your app to do something like store message record
/// Use a singleton in frameworks to remark if the app has launched
/// if not launched, use the code following
/// completion(INSendMessageIntentResponse(code: .failureRequiringAppLaunch, userActivity: nil))
} Confirm阶段是我们最后可以尝试修改intent事件中传递的数值的时候。要记住一点,完全精确的内容固然是最好的答案,但是过多的让Siri询问用户参数的详细信息也会导致用户的抵触
Handle阶段 Handle阶段不需要做太多额外的工作,判断一下消息接收者或消息内容是否存在,如果存在,执行类似保存/发送的工作,然后完成。否则告诉Siri本次的intent事件处理处理失败,我们还可以通过配置NSUserActivity对象来告诉Siri失败的原因
func handle(sendMessage intent: INSendMessageIntent, completion: (INSendMessageIntentResponse) -> Void) {
if intent.recipients != nil && intent.content != nil {
/// do some thing success send message
let success = LXDAccount.share().send(message: intent.content!, to: intent.recipients!)
completion(INSendMessageIntentResponse(code: success, userActivity: nil))
} else {
let userActivity = NSUserActivity(activityType: String(INSendMessageIntent))
userActivity.userInfo = [NSString(string: "error") : String("AppDidNotLaunch")]
completion(INSendMessageIntentResponse(code: .failure, userActivity: userActivity))
}
}