讓App在iOS12中支持Siri Shortcuts(捷徑)功能 和 “設(shè)置和捷徑App內(nèi)未列出自己App的Shortcut” 的解決辦法

最近發(fā)現(xiàn)的問(wèn)題 “設(shè)置和捷徑App內(nèi)未列出自己App的Shortcut” 的解決辦法在文章末尾或者我的github博客
網(wǎng)上的shortcuts介紹都沒(méi)有提及這一點(diǎn)腻贰,導(dǎo)致了一個(gè)疏忽,甚至以為是自動(dòng)添加的涎显。

文章轉(zhuǎn)自自己github博客
后續(xù)更新可能不會(huì)及時(shí)同步到簡(jiǎn)書限次,歡迎大家來(lái)我的github博客查看指教。
同時(shí)github屏蔽了baidu爬蟲,我的github博客無(wú)法通過(guò)百度搜索到赘来,很尷尬??栏渺,不想搭CDN不想搭Coding呛梆,暫時(shí)沒(méi)有更好解決辦法。

背景介紹

WWDC 2018 蘋果更新了Siri使其支持Shortcuts功能磕诊,中文名“捷徑”填物。支持用戶通過(guò)自定義把一系列操作合并到一個(gè)Shortcut內(nèi)。蘋果官方應(yīng)用提供了一些接口供Shortcut調(diào)用霎终,如Map應(yīng)用的“獲取行程時(shí)間”滞磺,“顯示路線”等。如果我們的應(yīng)用需要支持莱褒,需要自己在App中開(kāi)放可以被Shortcuts訪問(wèn)的接口击困。同時(shí)蘋果正在大力推廣這個(gè)Siri新功能,支持軟件可在蘋果App Store榜單“用 Siri广凸,走捷徑”中列出阅茶,有一定推廣作用。該功能也有利于增加用戶粘度和活躍人數(shù)谅海。

Apple提供了官方關(guān)于Shortcuts的demo脸哀,但是在蘋果大力推廣Swift的浪潮下,demo的語(yǔ)言也是Swift版的扭吁,無(wú)奈公司現(xiàn)在還在使用Objc撞蜂,下面介紹下Objc下的接入過(guò)程。

創(chuàng)建Custom Intent

在項(xiàng)目中通過(guò)“New File...”創(chuàng)建一個(gè)Intents.intentdefinition文件侥袜。這個(gè)文件用來(lái)定義自定義intent類型蝌诡。

SiriKitIntentDefinitionFile.png

CustomIntents.png

同時(shí)會(huì)自動(dòng)在項(xiàng)目的Info.plist文件中添加NSUserActivityTypes

InfoPlist.png

添加Frameworks

在項(xiàng)目的Build Phases中的Link Binary With Libraries中添加Intents.frameworkIntentsUI.framework

Frameworks.png

添加Shortcut按鈕

在項(xiàng)目中需要調(diào)用添加Shortcut按鈕的.m文件中系馆,

增加import

#import <Intents/Intents.h>
#import <IntentsUI/IntentsUI.h>
#import "HWTakePhotoIntent.h"   //上方“設(shè)置Custom Intents”圖中右邊箭頭指的“Class Name”

添加Delegate

<INUIAddVoiceShortcutButtonDelegate,
INUIAddVoiceShortcutViewControllerDelegate,
INUIEditVoiceShortcutViewControllerDelegate>

添加Property

@property (nonatomic, strong) HWTakePhotoIntent API_AVAILABLE(ios(12.0)) *intent;
@property (nonatomic, strong) INUIAddVoiceShortcutButton API_AVAILABLE(ios(12.0)) *shortcutButton;

添加shortcutButton按鈕

if (@available(iOS 12.0, *)) {
    _shortcutButton = [[INUIAddVoiceShortcutButton alloc] initWithStyle:INUIAddVoiceShortcutButtonStyleWhiteOutline];
    _shortcutButton.shortcut = [[INShortcut alloc] initWithIntent:self.intent];
    _shortcutButton.translatesAutoresizingMaskIntoConstraints = false;
    _shortcutButton.delegate = self;
    [self.view addSubview:_shortcutButton];
}

設(shè)置intent屬性

- (HWTakePhotoIntent *)intent API_AVAILABLE(ios(12.0)){
    if (!_intent) {
        _intent = [[HWTakePhotoIntent alloc] init];
        _intent.suggestedInvocationPhrase = @"開(kāi)始改作業(yè)";   //在Siri語(yǔ)音設(shè)置時(shí)顯示的建議設(shè)置喚起文字
    }
    return _intent;
}

設(shè)置對(duì)應(yīng)delegate方法

#pragma mark - INUIAddVoiceShortcutButtonDelegate
- (void)presentAddVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)addVoiceShortcutViewController forAddVoiceShortcutButton:(INUIAddVoiceShortcutButton *)addVoiceShortcutButton API_AVAILABLE(ios(12.0)){
    addVoiceShortcutViewController.delegate = self;
    [self presentViewController:addVoiceShortcutViewController animated:YES completion:nil];
}

- (void)presentEditVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)editVoiceShortcutViewController forAddVoiceShortcutButton:(INUIAddVoiceShortcutButton *)addVoiceShortcutButton API_AVAILABLE(ios(12.0)){
    editVoiceShortcutViewController.delegate = self;
    [self presentViewController:editVoiceShortcutViewController animated:YES completion:nil];
}

#pragma mark - INUIAddVoiceShortcutViewControllerDelegate
- (void)addVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)controller didFinishWithVoiceShortcut:(INVoiceShortcut *)voiceShortcut error:(NSError *)error
API_AVAILABLE(ios(12.0)){
    [controller dismissViewControllerAnimated:YES completion:nil];
}

- (void)addVoiceShortcutViewControllerDidCancel:(INUIAddVoiceShortcutViewController *)controller API_AVAILABLE(ios(12.0)){
    [controller dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - INUIEditVoiceShortcutViewControllerDelegate
- (void)editVoiceShortcutViewControllerDidCancel:(INUIEditVoiceShortcutViewController *)controller API_AVAILABLE(ios(12.0)){
    [controller dismissViewControllerAnimated:YES completion:nil];
}

- (void)editVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)controller didUpdateVoiceShortcut:(INVoiceShortcut *)voiceShortcut error:(NSError *)error API_AVAILABLE(ios(12.0)){
    [controller dismissViewControllerAnimated:YES completion:nil];
}

- (void)editVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)controller didDeleteVoiceShortcutWithIdentifier:(NSUUID *)deletedVoiceShortcutIdentifier API_AVAILABLE(ios(12.0)){
    [controller dismissViewControllerAnimated:YES completion:nil];
}

AppDelegate.m文件中添加方法

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
    // activityType 和 Info.plist中的NSUserActivityTypes內(nèi)容對(duì)應(yīng)
    if ([userActivity.activityType isEqualToString:@"HWTakePhotoIntent"]) {
        [HWNotificationCenter postNotificationName:kNotificationOpenCamera object:nil]; // 通過(guò)通知找到對(duì)應(yīng)class處理activity
    }
    return YES;
}

用于在Siri中通過(guò)設(shè)定語(yǔ)音調(diào)起應(yīng)用時(shí)處理Siri的請(qǐng)求送漠。我們的項(xiàng)目中是打開(kāi)攝像頭拍照批改作業(yè)。

iOS12 Siri Known Issues

iOS12SiriKnownIssues.png

如上圖紅框所示由蘑,iOS12發(fā)布后已知問(wèn)題之一是系統(tǒng)的INUIAddVoiceShortcutButton只支持默認(rèn)的標(biāo)題“Add to Siri”和“Added to Siri”闽寡,沒(méi)有做本地化支持??。此外按鈕的樣式也很死尼酿,無(wú)法自由自在的自定義爷狈,所以灰溜溜的只能自己來(lái)寫自定義按鈕了。

需求一:判斷是否添加過(guò)該shortcut來(lái)區(qū)別跳轉(zhuǎn)INUIAddVoiceShortcutViewController還是INUIEditVoiceShortcutViewController

當(dāng)然蘋果為我們提供了INVoiceShortcutCenter- (void)getAllVoiceShortcutsWithCompletion:(void(^)(NSArray<INVoiceShortcut *> * _Nullable voiceShortcuts, NSError * _Nullable error))completionHandler;方法來(lái)獲得所有添加的Shortcuts或者- (void)getVoiceShortcutWithIdentifier:(NSUUID *)identifier completion:(void(^)(INVoiceShortcut * _Nullable voiceShortcut, NSError * _Nullable error))completionHandler NS_SWIFT_NAME(getVoiceShortcut(with:completion:));通過(guò)identifier查找對(duì)應(yīng)的Shortcut裳擎。

我在項(xiàng)目中的按鈕點(diǎn)擊事件代碼如下:

- (void)shortcutButtonClicked:(UIButton *)sender
{
    if (@available(iOS 12.0, *)) {
        [[INVoiceShortcutCenter sharedCenter] getAllVoiceShortcutsWithCompletion:^(NSArray<INVoiceShortcut *> * _Nullable voiceShortcuts, NSError * _Nullable error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                BOOL tempAddedShortcut = NO;
                for (INVoiceShortcut *voiceShortcut in voiceShortcuts) {
                    if ([voiceShortcut.shortcut.intent isKindOfClass:[HWTakePhotoIntent class]]) {
                        tempAddedShortcut = YES;
                        break;
                    }
                }
                self.addedShortcut = tempAddedShortcut;
                if (self.addedShortcut) {
                    INUIEditVoiceShortcutViewController *editVoiceShortcutViewController = [[INUIEditVoiceShortcutViewController alloc] initWithVoiceShortcut:voiceShortcuts[0]];
                    editVoiceShortcutViewController.delegate = self;
                    [self presentViewController:editVoiceShortcutViewController animated:YES completion:nil];
                } else {
                    INShortcut *shortcut = [[INShortcut alloc] initWithIntent:self.intent];
                    INUIAddVoiceShortcutViewController *addVoiceShortcutViewController = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortcut];
                    addVoiceShortcutViewController.delegate = self;
                    [self presentViewController:addVoiceShortcutViewController animated:YES completion:nil];
                }
            });
        }];
    }
}

需求二:通過(guò)INUIAddVoiceShortcutViewControllerINUIEditVoiceShortcutViewController的Delegates更新自定義Shortcut按鈕狀態(tài)

同樣也需要用到需求一中提到的判斷是否添加過(guò)當(dāng)前Shortcut來(lái)更新對(duì)應(yīng)的自定義Shortcut按鈕樣式涎永。

“設(shè)置和捷徑App內(nèi)未列出自己App的Shortcut” 的解決辦法

問(wèn)題描述

按照上文介紹,一步步在自己的App中添加Shortcut功能成功后,我們并不能在系統(tǒng)的設(shè)置應(yīng)用的Siri 與 搜索中看到我們剛剛添加的Shortcut羡微,或者在捷徑應(yīng)用中找到谷饿。如下圖:

SettingMenuWithoutShortcuts.PNG

如果我們通過(guò)上文中定義的App內(nèi)的Add to Siri按鈕添加用戶的Shortcut到Siri成功后,我們依然可以在設(shè)置捷徑應(yīng)用中看到妈倔。但是如果刪除添加的Shortcut博投,有都會(huì)消失。這顯然不是我們需要的效果盯蝴。

預(yù)期效果是不管用戶是否在App內(nèi)添加Shortcut到Siri毅哗,都應(yīng)在設(shè)置捷徑應(yīng)用中看到。

解決辦法

我們需要自己手動(dòng)更新我們應(yīng)用的Shortcut Suggestions的內(nèi)容捧挺,這樣才能在設(shè)置捷徑應(yīng)用中列出虑绵。

更新Shortcut Suggestions內(nèi)容的代碼如下。

- (void)addMenuItemShortcuts
{
    if (AVAILABLE(12.0)) {
        HWTakePhotoIntent *intent = [[HWTakePhotoIntent alloc] init];
        intent.suggestedInvocationPhrase = NSLocalizedString(@"SIRI_SHORTCUT_CORRECT_WORK", nil);
        [[INVoiceShortcutCenter sharedCenter] setShortcutSuggestions:@[[[INShortcut alloc] initWithIntent:intent]]];
    }
}

我是在AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions里做了初始化闽烙。

更新Shortcut Suggestions內(nèi)容后翅睛,即使不在應(yīng)用內(nèi)添加Shortcut到Siri,在設(shè)置捷徑應(yīng)用中仍能找到應(yīng)用提供的Shortcut建議鸣峭。

設(shè)置中的界面如下

SettingMenuWithShortcuts.PNG

點(diǎn)擊捷徑進(jìn)入后如下

SettingMenuWithShortcutsContent.PNG

如果你需要宏所,也可以在其他需要的時(shí)候更新Shortcut Suggestions內(nèi)容。

總結(jié)

Siri Shortcut大功告成

References:

iOS12 Siri Shortcuts初探

Human Interface Guidelines - SiriKit

Documentation - SiriKit

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末摊溶,一起剝皮案震驚了整個(gè)濱河市爬骤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莫换,老刑警劉巖霞玄,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拉岁,居然都是意外死亡坷剧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門喊暖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惫企,“玉大人,你說(shuō)我怎么就攤上這事陵叽∧” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵巩掺,是天一觀的道長(zhǎng)偏序。 經(jīng)常有香客問(wèn)我,道長(zhǎng)胖替,這世上最難降的妖魔是什么研儒? 我笑而不...
    開(kāi)封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任豫缨,我火速辦了婚禮,結(jié)果婚禮上端朵,老公的妹妹穿的比我還像新娘好芭。我一直安慰自己,他們只是感情好冲呢,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布栓撞。 她就那樣靜靜地躺著,像睡著了一般碗硬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瓢颅,一...
    開(kāi)封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天恩尾,我揣著相機(jī)與錄音,去河邊找鬼挽懦。 笑死翰意,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的信柿。 我是一名探鬼主播冀偶,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼渔嚷!你這毒婦竟也來(lái)了进鸠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤形病,失蹤者是張志新(化名)和其女友劉穎客年,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體漠吻,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡量瓜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了途乃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绍傲。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖耍共,靈堂內(nèi)的尸體忽然破棺而出烫饼,到底是詐尸還是另有隱情,我是刑警寧澤划提,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布枫弟,位于F島的核電站,受9級(jí)特大地震影響鹏往,放射性物質(zhì)發(fā)生泄漏淡诗。R本人自食惡果不足惜骇塘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望韩容。 院中可真熱鬧款违,春花似錦、人聲如沸群凶。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)请梢。三九已至赠尾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毅弧,已是汗流浹背气嫁。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留够坐,地道東北人寸宵。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像元咙,于是被迫代替她去往敵國(guó)和親梯影。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345