玩轉iOS開發:iOS 10 新特性《Siri Kit》

CainLuo發表於2017-06-19

文章分享至我的個人技術部落格: 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:

1

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


最後

碼字很費腦, 看官賞點飯錢可好

微信

支付寶

相關文章