简单些了一下,有不足往谅解。
demo
什么是shortcut?
简单说就是往Sir里添加一条语音指令,通过Siri呼出指令后,打开对应的app,并跳转到指定页面。
如何集成
-
头文件依赖
#import <CoreSpotlight/CoreSpotlight.h>
#import <IntentsUI/IntentsUI.h>
#import <Intents/Intents.h> //其中包含了#import <CoreSpotlight/CoreSpotlight.h>
-
由于shortcut是iOS12才出现的,所有的操作都应该符号系统要求
if (@available(iOS 12.0, *)) {
NSString *invocationPhrase = @"哈哈哈";
[self isInvocationPhraseExist:invocationPhrase block:^(BOOL exist, INVoiceShortcut *voiceShortcut) {
[self donateShortCutsWithInvocationPhrase:invocationPhrase exist:exist voiceShortcut:voiceShortcut];
}];
}
-
添加新的shortcut之前要先判断指令是否已经添加过
查询操作是在子线程中执行的,拿到查询结果之后要返回主线程
/**
判断捷径是否已经存在
*/
- (void)isInvocationPhraseExist:(NSString *)invocationPhrase block:(void (^)(BOOL exist, INVoiceShortcut *voiceShortcut))block API_AVAILABLE(ios(12.0)){
NSLog(@"currentThread:%@", [NSThread currentThread]);//主线程
//获取该app已经添加过的捷径,避免重复添加
[[INVoiceShortcutCenter sharedCenter] getAllVoiceShortcutsWithCompletion:^(NSArray<INVoiceShortcut *> * _Nullable voiceShortcuts, NSError * _Nullable error) {
if (!error) {
dispatch_async(dispatch_get_main_queue(), ^{
BOOL exist = NO;
INVoiceShortcut *voiceShortcut = nil;
for (INVoiceShortcut *shortcut in voiceShortcuts) {
if ([shortcut.invocationPhrase isEqualToString:invocationPhrase]) {
exist = YES;
voiceShortcut = shortcut;
break;
} else {
exist = NO;
}
}
block(exist, voiceShortcut);
});
}
}];
}
-
创建或者修改shortcut
指令不存在则添加,存在则修改
/**
创建或者修改语音捷径
@param invocationPhrase 提示的语音输入语句
@param exist 是否已经存在
@param voiceShortcut 已经存在的语音语句
*/
- (void)donateShortCutsWithInvocationPhrase:(NSString *)invocationPhrase exist:(BOOL)exist voiceShortcut:(INVoiceShortcut *)voiceShortcut API_AVAILABLE(ios(12.0)){
NSUserActivity *activity = [[NSUserActivity alloc] initWithActivityType:@"com.cc.siri"];
activity.eligibleForSearch = YES;
activity.title = @"我是title";
activity.eligibleForPrediction = YES;
activity.suggestedInvocationPhrase = invocationPhrase;
CSSearchableItemAttributeSet *set = [[CSSearchableItemAttributeSet alloc] init];
set.thumbnailData = UIImagePNGRepresentation([UIImage imageNamed:@"icon"]);
set.contentDescription = @"我是描述";
activity.contentAttributeSet = set;
INShortcut *shortCut = [[INShortcut alloc] initWithUserActivity:activity];
if (!exist) { //添加
INUIAddVoiceShortcutViewController *shortCutVc = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortCut];
shortCutVc.delegate = self;
[self presentViewController:shortCutVc animated:YES completion:nil];
} else { //修改 此处需要用已经存在的voiceShortcut来初始化控制器
INUIEditVoiceShortcutViewController *shortCutVc = [[INUIEditVoiceShortcutViewController alloc] initWithVoiceShortcut:voiceShortcut];
shortCutVc.delegate = self;
[self presentViewController:shortCutVc animated:YES completion:nil];
}
}
-
事件处理
在appdelefate中监听,根据userActivity.activityType对不同的指令做相应的处理
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
if ([userActivity.activityType isEqualToString:@"com.cc.siri"]) {
//代码块
}
return YES;
}
-
代理
添加和修改有不同的代理,都要分别实现
-
添加 INUIAddVoiceShortcutViewControllerDelegate
两个方法:
/*!
@abstract Called after the user finishes the setup flow for the voice shortcut, with either the successfully-added voice shortcut, or an error.
@discussion Your implementation of this method should dismiss the view controller.
*/
- (void)addVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)controller didFinishWithVoiceShortcut:(nullable INVoiceShortcut *)voiceShortcut error:(nullable NSError *)error;
/*!
@abstract Called if the user cancels the setup flow; the voice shortcut was not added.
@discussion Your implementation of this method should dismiss the view controller.
*/
- (void)addVoiceShortcutViewControllerDidCancel:(INUIAddVoiceShortcutViewController *)controller;
-
修改 INUIEditVoiceShortcutViewControllerDelegate
三个方法:
/*!
@abstract Called if the user updates the voice shortcut, with either the successfully-updated voice shortcut, or an error.
@discussion Your implementation of this method should dismiss the view controller.
*/
- (void)editVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)controller didUpdateVoiceShortcut:(nullable INVoiceShortcut *)voiceShortcut error:(nullable NSError *)error;
/*!
@abstract Called if the user deletes the voice shortcut.
@discussion Your implementation of this method should dismiss the view controller.
*/
- (void)editVoiceShortcutViewController:(INUIEditVoiceShortcutViewController *)controller didDeleteVoiceShortcutWithIdentifier:(NSUUID *)deletedVoiceShortcutIdentifier;
/*!
@abstract Called if the user cancelled; no changes were made to the voice shortcut.
@discussion Your implementation of this method should dismiss the view controller.
*/
- (void)editVoiceShortcutViewControllerDidCancel:(INUIEditVoiceShortcutViewController *)controller;
注意
-
suggestedInvocationPhrase在分类里
NSUserActivity的.h中并没有属性suggestedInvocationPhrase,该属性其实是在分类NSUserActivity+IntentsAdditions里面,需要导入头文件
#import <Intents/NSUserActivity+IntentsAdditions.h>
Intents/Intents.h中包含了#import <CoreSpotlight/CoreSpotlight.h>
-
查询是否添加过指令时,下面代码新开了一个线程,拿到结果后需要返回主线程
[[INVoiceShortcutCenter sharedCenter] getAllVoiceShortcutsWithCompletion:^(NSArray<INVoiceShortcut *> * _Nullable voiceShortcuts, NSError * _Nullable error) {
}
网友评论