iOS 12 新特性 Sirishortcut(捷徑)調(diào)研(二)

通過Intents創(chuàng)建捷徑

intents的方式實(shí)現(xiàn)捷徑度帮,可以做更深一步的定制曙强,甚至無需打開APP使用應(yīng)用的一些功能

首先創(chuàng)建Intents.intentdefinition文件

通過File -> New File, 然后選擇 “SiriKit Intent Definition File.”創(chuàng)建自定義的intent文件莉恼,步驟如下圖:

Sirishortcut_new_intent.jpg

創(chuàng)建好的intent文件如下:

Sirishortcut_intent_content.jpg

每一個intent都對應(yīng)一個response如下圖:

Sirishortcut_response_content.jpg

創(chuàng)建完成后囚枪,編譯Intents.intentdefinition關(guān)聯(lián)的target xcode會自動生成對應(yīng)的類文件发笔,但是在工程中找不到類文件缸榛,可以通過如下方法查看:

Sirishortcut_look_info.jpg

編譯后xcode自動生成的類文件如下:


Sirishortcut_Intent_class_info.jpg

類文件包含QuickOrderCoffeeIntent類實(shí)現(xiàn)以及 QuickOrderCoffeeIntentHandling協(xié)議和 QuickOrderCoffeeIntentResponse類等所需要的內(nèi)容吝羞。

下面就可以在工程中直接 #import "QuickOrderCoffeeIntent.h"使用。
這里我們想要在用戶再點(diǎn)擊來一單的時候内颗,創(chuàng)建快捷下單的shortcut

- (void)donateInteraction {
    if (@available(iOS 12.0, *)) {
        QuickOrderCoffeeIntent *quickOrderIntent = [[QuickOrderCoffeeIntent alloc] init];
        quickOrderIntent.name = @"CafeAmericano";
        quickOrderIntent.kind = @"Americano";
        INInteraction *interaction = [[INInteraction alloc] initWithIntent:quickOrderIntent response:nil];
        [interaction donateInteractionWithCompletion:^(NSError * _Nullable error) {
            
        }];
    }
}

自定義的Intent如果沒有關(guān)聯(lián)到主工程的target钧排,要先進(jìn)行關(guān)聯(lián)
自定義intent的內(nèi)容到此就結(jié)束了,下面需要結(jié)合Intent Extension 和Intent UI Extension深度定制捷徑均澳。

添加Intents Extension 和Intents Extension UI

通過target添加Siri擴(kuò)展 new -> target 如下圖:

Sirishortcut_new_target.jpg

這里新建名為QuickOrder的target 同時勾選 UI Extentsion如下圖

Sirishortcut_new_ui_target.jpg

這時就會同時創(chuàng)建Siri Extentsion 和 Siri ExtentSion UI 兩個target如下圖:

Sirishortcut_target_list.jpg

接下來需要修改Extentsion 和Extentsion UI 目錄下的info.plist 將之前自定義的type注冊進(jìn)去卖氨,如下圖

Sirishortcut_infoPlist_type_string.jpg

下面來看一下創(chuàng)建的Extentsion 和Extentsion UI
IntentHandler 類,導(dǎo)入自定義的Intent 遵循協(xié)議

#import "QuickOrderCoffeeIntent.h"
NS_ASSUME_NONNULL_BEGIN

@interface QuickOrderIntentHandler : INExtension<QuickOrderCoffeeIntentHandling>

@end

NS_ASSUME_NONNULL_END

實(shí)現(xiàn)如下兩個方法

- (void)confirmQuickOrderCoffee:(QuickOrderCoffeeIntent *)intent completion:(void (^)(QuickOrderCoffeeIntentResponse *response))completion NS_SWIFT_NAME(confirm(intent:completion:)) {
    NSLog(@"%s",__func__);
    if (!isLogin) {//如果沒有登錄 則返回之前定義的code QuickOrderCoffeeIntentResponseCodeFaiureUnLogin
        QuickOrderCoffeeIntentResponse *unLoginResponse = [[QuickOrderCoffeeIntentResponse alloc] initWithCode:QuickOrderCoffeeIntentResponseCodeFaiureUnLogin userActivity:nil];
        completion(unLoginResponse);
    } else {
        if (haveProduct) {//如果有庫存  返回ready
            QuickOrderCoffeeIntentResponse *readyResponse = [[QuickOrderCoffeeIntentResponse alloc] initWithCode:QuickOrderCoffeeIntentResponseCodeReady userActivity:nil];
            completion(readyResponse);
        } else { //拋出沒有庫存的code返回
            QuickOrderCoffeeIntentResponse *outOfResponse = [[QuickOrderCoffeeIntentResponse alloc] initWithCode:QuickOrderCoffeeIntentResponseCodeFailureOutOfStock userActivity:nil];
            completion(outOfResponse);
        }
    }
    QuickOrderCoffeeIntentResponse *defaultResponse = [[QuickOrderCoffeeIntentResponse alloc] initWithCode:QuickOrderCoffeeIntentResponseCodeFailure userActivity:nil];
    completion(defaultResponse);
}

- (void)handleQuickOrderCoffee:(nonnull QuickOrderCoffeeIntent *)intent completion:(nonnull void (^)(QuickOrderCoffeeIntentResponse * _Nonnull))completion {
    NSLog(@"%s",__func__);
    QuickOrderCoffeeIntentResponse *quickOrderresonse = [[QuickOrderCoffeeIntentResponse alloc] initWithCode:QuickOrderCoffeeIntentResponseCodeSuccess userActivity:nil];
    completion(quickOrderresonse);
}

下面講解一下上述代碼做了什么
Intent處理程序涉及三個步驟:

  • 解析(Resolve)
  • 確認(rèn)(Confirm)
  • 處理(Handle)
    shortcut 沒有了Siri解析的過程会烙,會直接進(jìn)行 confirm 和 handle
    這里對應(yīng)confirmQuickOrderCoffeehandleQuickOrderCoffee

confirm階段
預(yù)訂咖啡首先確認(rèn)登錄狀態(tài),如果沒有登錄 可以拋出自定義未登錄的code QuickOrderCoffeeIntentResponseCodeFaiureUnLogin 提供給UI層做相關(guān)處理你可以根據(jù)程序所處的狀態(tài)碼筒捺,渲染對應(yīng)的UI柏腻,如果是未登錄可以打開APP進(jìn)行登錄(QuickOrderCoffeeIntentResponseCodeFailureRequiringAppLaunch)
在進(jìn)行庫存的判斷 如果沒有庫存 拋出 QuickOrderCoffeeIntentResponseCodeFailureOutOfStock
一系列檢查之后,下單的條件滿足了 我們可以返回 QuickOrderCoffeeIntentResponseCodeReady
handle階段
可以進(jìn)行下單的請求系吭,處理完成后五嫂,如果下單成功,可以回調(diào) QuickOrderCoffeeIntentResponseCodeSuccess
以上就是下單的大概流程

IntentViewController 類 作為自定義UI的視圖控制器肯尺,可以根據(jù)下單的步驟沃缘,做相關(guān)的UI渲染。這里創(chuàng)建了兩種狀態(tài)的視圖则吟,分別顯示商品信息槐臀,和預(yù)訂結(jié)果

Sirishortcut_UI_Class@2x.jpg
// Prepare your view controller for the interaction to handle.
- (void)configureViewForParameters:(NSSet <INParameter *> *)parameters ofInteraction:(INInteraction *)interaction interactiveBehavior:(INUIInteractiveBehavior)interactiveBehavior context:(INUIHostedViewContext)context completion:(void (^)(BOOL success, NSSet <INParameter *> *configuredParameters, CGSize desiredSize))completion {
    // Do configuration here, including preparing views and calculating a desired size for presentation.
    
    if (interaction.intentHandlingStatus == INIntentHandlingStatusReady) {
        [self.view addSubview:self.quickOrderVC.view];
        [self.quickOrderVC.view setTranslatesAutoresizingMaskIntoConstraints:NO];
        //設(shè)置寬高
        [[self.quickOrderVC.view.widthAnchor constraintEqualToAnchor:self.view.widthAnchor] setActive:YES];
         [[self.quickOrderVC.view.heightAnchor constraintEqualToAnchor:self.view.heightAnchor] setActive:YES];
         [[self.quickOrderVC.view.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] setActive:YES];
         [[self.quickOrderVC.view.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] setActive:YES];
        
        [self.quickOrderVC didMoveToParentViewController:self];
        if (completion) {
            completion(YES, parameters, [self desiredSize]);
        }
    } else if (interaction.intentHandlingStatus == INIntentHandlingStatusSuccess) {
        [self.view addSubview:self.orderResultVC.view];
        [self.orderResultVC.view setTranslatesAutoresizingMaskIntoConstraints:NO];
        //設(shè)置寬高
        [[self.orderResultVC.view.widthAnchor constraintEqualToAnchor:self.view.widthAnchor] setActive:YES];
        [[self.orderResultVC.view.heightAnchor constraintEqualToAnchor:self.view.heightAnchor] setActive:YES];
        [[self.orderResultVC.view.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] setActive:YES];
        [[self.orderResultVC.view.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] setActive:YES];
        [self.orderResultVC didMoveToParentViewController:self];
        if (completion) {
            completion(YES, parameters, [self desiredSize]);
        }
    }
    else {
        if (completion) {
            completion(NO, parameters, [self desiredSize]);
        }
    }
}

以上方法 根據(jù) IntentHandler類中返回的狀態(tài)code,做對應(yīng)的UI渲染
code 如果是系統(tǒng)自動創(chuàng)建的氓仲,會和 interaction.intentHandlingStatus 相互對應(yīng)水慨。如果是自定義的code,他們的 intentHandlingStatus 都對應(yīng)INIntentHandlingStatusSuccess
可以參考如下代碼做相關(guān)處理

    if ([interaction.intentResponse isKindOfClass:[QuickOrderCoffeeIntentResponse class]]) {
        QuickOrderCoffeeIntentResponse *quickOrderResponse = (QuickOrderCoffeeIntentResponse *)interaction.intentResponse;
        if (quickOrderResponse.code == QuickOrderCoffeeIntentResponseCodeFaiureUnLogin) {
            ///MARK:未登錄操作
        } else if (quickOrderResponse.code == QuickOrderCoffeeIntentResponseCodeFailureOutOfStock) {
            ///MARK:沒有庫存
        }
        
    }

核心的功能到這里就算完成了敬扛∥鳎回到最開始的需求,我們希望在用戶點(diǎn)擊再來一單的時候啥箭,生成快捷下單的shortcut
donate 的代碼如下:

- (void)donateInteraction {
    if (@available(iOS 12.0, *)) {
        QuickOrderCoffeeIntent *quickOrderIntent = [[QuickOrderCoffeeIntent alloc] init];
        quickOrderIntent.name = @"CafeAmericano";
        quickOrderIntent.kind = @"Americano";
        INInteraction *interaction = [[INInteraction alloc] initWithIntent:quickOrderIntent response:nil];
        [interaction donateInteractionWithCompletion:^(NSError * _Nullable error) {
            
        }];
    }
}

我們還可以引導(dǎo)用戶將快捷下單的shortcut添加到Siri短語

- (void)addShortcutsToSiri {
    if (@available(iOS 12.0, *)) {
        QuickOrderCoffeeIntent *quickOrderIntent = [[QuickOrderCoffeeIntent alloc] init];
        INShortcut *shortcut = [[INShortcut alloc] initWithIntent:quickOrderIntent];

        INUIAddVoiceShortcutViewController *vc = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortcut];
        vc.delegate = self;
        [self presentViewController:vc animated:YES completion:nil];
    }
}

通過Intent的方式定義Sirishortcut到這里就算完成了谍珊。

效果圖
Sirishortcut_desc_1.jpg
Sirishortcut_desc_2.jpg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市急侥,隨后出現(xiàn)的幾起案子砌滞,更是在濱河造成了極大的恐慌,老刑警劉巖坏怪,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件布持,死亡現(xiàn)場離奇詭異,居然都是意外死亡陕悬,警方通過查閱死者的電腦和手機(jī)题暖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捉超,“玉大人胧卤,你說我怎么就攤上這事∑丛溃” “怎么了枝誊?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惜纸。 經(jīng)常有香客問我叶撒,道長绝骚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任祠够,我火速辦了婚禮压汪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘古瓤。我一直安慰自己止剖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布落君。 她就那樣靜靜地躺著穿香,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绎速。 梳的紋絲不亂的頭發(fā)上皮获,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音纹冤,去河邊找鬼洒宝。 笑死,一個胖子當(dāng)著我的面吹牛赵哲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播君丁,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枫夺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绘闷?” 一聲冷哼從身側(cè)響起橡庞,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎印蔗,沒想到半個月后扒最,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡华嘹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年吧趣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耙厚。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡强挫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出薛躬,到底是詐尸還是另有隱情俯渤,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布型宝,位于F島的核電站八匠,受9級特大地震影響絮爷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梨树,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一坑夯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劝萤,春花似錦渊涝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至厌处,卻和暖如春鳖谈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阔涉。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工缆娃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瑰排。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓贯要,卻偏偏與公主長得像,于是被迫代替她去往敵國和親椭住。 傳聞我的和親對象是個殘疾皇子崇渗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容