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

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


Siri

众所周知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目前支持的一些种类, 更加详细的文档请看官方文档.

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

New Project

创建新工程的项目这里我就忽略了, 直接来看添加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的流程

关于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文件, 这里我们要开始写代码了, 我们需要些一个精确的用户名称匹配和一个模糊的用户名称匹配:

    // 遍历待匹配选项
    for (INPerson *recipient in recipients) {
        
        // Implement your contact matching logic here to create an array of matching contacts
        NSMutableArray<INPerson *> *matchingContacts = [NSMutableArray array];
        
        // 待匹配的名称
        NSString *recipientName = recipient.displayName;
        NSString *recipientNamePinYin = [recipientName cl_PinYin];
        
        // 精确的匹配到列表里的用户
        UserList *user = [UserList checkUserWithName:recipientName];
        
        if (user) {
            
            NSLog(@"匹配到精确用户:%@", user);
    
            // 创建一个匹配成功的用户
            INPersonHandle *personHandle = [[INPersonHandle alloc] initWithValue:user.userAddress
                                                                            type:INPersonHandleTypeEmailAddress];
            INImage *iconImage = [INImage imageNamed:user.userIcon];
            
            INPerson *person = [[INPerson alloc] initWithPersonHandle:personHandle
                                                       nameComponents:nil
                                                          displayName:recipientName
                                                                image:iconImage
                                                    contactIdentifier:nil
                                                     customIdentifier:nil
                                                              aliases:nil
                                                       suggestionType:INPersonSuggestionTypeSocialProfile];
            
            // 把匹配成功的用户记录下来
            [matchingContacts addObject:person];
        }
        
        // 如果没有精确匹配到用户, 则用模糊匹配
        if (matchingContacts.count == 0) {
            
            NSLog(@"没有匹配到精确用户:%@", user);

            for (UserList *user in [UserList userList]) {
                
                // 匹配用户的名称
                NSString *userName = user.userName;
                NSString *userNamePinYin = [userName cl_PinYin];
                
                if ([recipientName containsString:userName] || [recipientNamePinYin containsString:userNamePinYin]) {
                    
                    //  创建一个匹配成功的用户
                    INPersonHandle *personHandle = [[INPersonHandle alloc] initWithValue:user.userAddress
                                                                                    type:INPersonHandleTypeEmailAddress];
                    
                    INImage *iconImage = [INImage imageNamed:user.userIcon];
                    
                    INPerson *person = [[INPerson alloc] initWithPersonHandle:personHandle
                                                               nameComponents:nil
                                                                  displayName:userName
                                                                        image:iconImage
                                                            contactIdentifier:nil
                                                             customIdentifier:nil
                                                                      aliases:nil
                                                               suggestionType:INPersonSuggestionTypeSocialProfile];
                    
                    //  记录匹配的用户
                    [matchingContacts addObject:person];
                }
            }
        }
复制代码

 

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
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。