原文网址:玩转iOS开发:iOS 10 新特性《Siri Kit》 – 掘金 (juejin.cn)

文章分享至我的个人技术博客: https://cainluo.github.io/14977885999456.html


众所周知Siri是苹果爸爸内置在iOS系统的一个语音助手, 自从在2011年的iPhone 4s问世之后, Siri就一直受关注.

但好景不长, 随着Siri的功能和权限太弱了, 慢慢就被人遗忘, 起码我身边用iPhone的小伙伴都会把Siri给关掉, 按照他们的说法就是可以省电…我也是醉了.

几年过去后, Siri终于迎接来了春天, 随着iOS 10的推出, 终于给开发者们开放了Siri Kit, 也开放了Siri Intents Extension, 国内用的最快的App依然还是BAT巨头的产品, 比如QQ.

这里的工程是Objective-C版本, 想看Swift版本的, 可以到这里去查看.


这里我简单的举一下Siri目前支持的一些种类, 更加详细的文档请看官方文档.

Siri服务类型 Intent种类
VoIP语音 – VoIP calling INStartVideoCallIntent、INStartAudioCallIntent
消息 – Messaging INSendMessageIntent
支付 – Payments INSendPaymentIntent、INRequestPaymentIntent
图片 – Photos INSearchForPhotosIntent
健身 – Workouts INEndWorkoutIntent、INPauseWorkoutIntent 、INStartWorkoutIntent 、 INResumeWorkoutIntent 、INCancelWorkoutIntent
骑行预约 – Ride booking INRequestRideIntent、INGetRideStatusIntent、 INListRideOptionsIntent、 INGetRideStatusIntent
汽车状态 – Car commands INSetCarLockStatusIntent、INGetCarPowerLevelStatusIntent、INActivateCarSignalIntent
车载系统 – CarPlay INSetAudioSourceInCarIntent、INSetClimateSettingsInCarIntent
预定餐厅 – Restaurant reservations INBookRestaurantReservationIntent

创建新工程的项目这里我就忽略了, 直接来看添加Siri Intents Extension:

2

 

这里注意一下, 我们要把Include UI Extension也要勾上, 但这个东西会专门开一篇文章去讲解.

3

 

创建好之后, 我们可以看到Siri Intents Extension和之前我们遇到的Extension不太一样:

 

4

 

还有就是, 我们打开Siri Intents ExtensionInfo.plist文件看到IntentsSupportedIntentsRestrictedWhileLocked, 那有什么用呢?

  • IntentsSupported: 我们项目需要支持的Siri Intents就放到这里, 比如我们在工程里看到的INSendMessageIntent, INSearchForMessagesIntent, INSetMessageAttributeIntent.

  • IntentsRestrictedWhileLocked: 在锁屏状态下需要锁定的Siri Intents就放到这里, 比如我们在工程里看到的INSendMessageIntent.

 

5

 


关于SiriKit的流程这里我就拷贝一下官方的说法:

 

6

 

SiriMaps通过Intents extension的扩展方式和我们的应用进行交互,其中,类型为INExtension的对象扮演着Intents extension扩展中直接协同Siri对象共同响应用户请求的关键角色。当我们实现了Intents extension扩展并产生了一个Siri请求事件时,一个典型的Intent事件的处理过程中总共有这三个步骤ResolveConfirmHandle

  • Resolve阶段。在Siri获取到用户的语音输入之后,生成一个INIntent对象,将语音中的关键信息提取出来并且填充对应的属性。这个对象在稍后会传递给我们设置好的INExtension子类对象进行处理,根据子类遵循的不同服务protocol来选择不同的解决方案。
  • Confirm阶段。在上一个阶段通过handler(for intent:)返回了处理intent的对象,此阶段会依次调用confirm打头的实例方法来判断Siri填充的信息是否完成。匹配的判断结果包括Exactly one matchTwo or more matches以及No match三种情况。这个过程中可以让Siri向用户征求更具体的参数信息。
  • confirm方法执行完成之后,Siri进行最后的处理阶段,生成答复对象,并且向此intent对象确认处理结果然后执显示结果给用户看。

7

 


这里我们首先要创建一个名单, 用来模拟一下发送消息的场景:

 

8

 

这里还有一个NSString的类别, 用来转换拼音的:

 

9

 


回到我们的IntentHandler.m文件, 这里我们要开始写代码了, 我们需要些一个精确的用户名称匹配和一个模糊的用户名称匹配:

  1. // 遍历待匹配选项
  2. for (INPerson *recipient in recipients) {
  3. // Implement your contact matching logic here to create an array of matching contacts
  4. NSMutableArray<INPerson *> *matchingContacts = [NSMutableArray array];
  5. // 待匹配的名称
  6. NSString *recipientName = recipient.displayName;
  7. NSString *recipientNamePinYin = [recipientName cl_PinYin];
  8. // 精确的匹配到列表里的用户
  9. UserList *user = [UserList checkUserWithName:recipientName];
  10. if (user) {
  11. NSLog(@"匹配到精确用户:%@", user);
  12. // 创建一个匹配成功的用户
  13. INPersonHandle *personHandle = [[INPersonHandle alloc] initWithValue:user.userAddress
  14. type:INPersonHandleTypeEmailAddress];
  15. INImage *iconImage = [INImage imageNamed:user.userIcon];
  16. INPerson *person = [[INPerson alloc] initWithPersonHandle:personHandle
  17. nameComponents:nil
  18. displayName:recipientName
  19. image:iconImage
  20. contactIdentifier:nil
  21. customIdentifier:nil
  22. aliases:nil
  23. suggestionType:INPersonSuggestionTypeSocialProfile];
  24. // 把匹配成功的用户记录下来
  25. [matchingContacts addObject:person];
  26. }
  27. // 如果没有精确匹配到用户, 则用模糊匹配
  28. if (matchingContacts.count == 0) {
  29. NSLog(@"没有匹配到精确用户:%@", user);
  30. for (UserList *user in [UserList userList]) {
  31. // 匹配用户的名称
  32. NSString *userName = user.userName;
  33. NSString *userNamePinYin = [userName cl_PinYin];
  34. if ([recipientName containsString:userName] || [recipientNamePinYin containsString:userNamePinYin]) {
  35. // 创建一个匹配成功的用户
  36. INPersonHandle *personHandle = [[INPersonHandle alloc] initWithValue:user.userAddress
  37. type:INPersonHandleTypeEmailAddress];
  38. INImage *iconImage = [INImage imageNamed:user.userIcon];
  39. INPerson *person = [[INPerson alloc] initWithPersonHandle:personHandle
  40. nameComponents:nil
  41. displayName:userName
  42. image:iconImage
  43. contactIdentifier:nil
  44. customIdentifier:nil
  45. aliases:nil
  46. suggestionType:INPersonSuggestionTypeSocialProfile];
  47. // 记录匹配的用户
  48. [matchingContacts addObject:person];
  49. }
  50. }
  51. }
  52. 复制代码

 

10

 


注意一下, 虽然我们代码写好了, 但我们还是需要看看工程里有没有添加-ObjC

 

11

 

还有就是Siri Intents ExtensionSiri Intents Extension UI里有没有链接好NSString+PinYin.mUserList.m:

 

12

 

 

13

 

不然就会发生"_OBJC_CLASS_$_UserList", referenced from:错误了.

在运行之前一定要到设置 -> Siri -> 开启Siri才可以使用, 这里我是用模拟器, 所以没法试着发邮件出去:

 

14

 

但是发消息还是ok得, 效果:

 

15

 

 

16

 

 

17

 


最后我们来看看额外的一篇文章, 就是企鹅公司是肿么给QQ适配SiriKit的一些思路QQ适配 SiriKit.


项目地址: https://github.com/CainRun/iOS-10-Characteristic/tree/master/9.Siri%20Intents

作者:CainLuo
链接:https://juejin.cn/post/6844903481942376455
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。