最近發(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
類型蝌诡。
同時(shí)會(huì)自動(dòng)在項(xiàng)目的Info.plist
文件中添加NSUserActivityTypes
添加Frameworks
在項(xiàng)目的Build Phases中的Link Binary With Libraries中添加Intents.framework
和IntentsUI.framework
。
添加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
如上圖紅框所示由蘑,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ò)INUIAddVoiceShortcutViewController
和INUIEditVoiceShortcutViewController
的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)用中找到谷饿。如下圖:
如果我們通過(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è)置
中的界面如下
點(diǎn)擊捷徑
進(jìn)入后如下
如果你需要宏所,也可以在其他需要的時(shí)候更新Shortcut Suggestions內(nèi)容。
總結(jié)
Siri Shortcut大功告成