INShortcut
这是Shortcut开发中要实现的核心class,我们看下这个类所提供的api:
API_AVAILABLE(ios(12.0), watchos(5.0)) API_UNAVAILABLE(tvos) API_UNAVAILABLE(macosx)
@interface INShortcut : NSObject
/*!
@abstract The intent that will be performed when this shortcut is invoked.
@discussion Is @c nil if the shortcut was created with a @c NSUserActivity.
*/
@property (readonly, copy, nullable, NS_NONATOMIC_IOSONLY) INIntent *intent;
/*!
@abstract The user activity that will be performed when this shortcut is invoked.
@discussion Is @c nil if the shortcut was created with an @c INIntent.
*/
@property (readonly, strong, nullable, NS_NONATOMIC_IOSONLY) NSUserActivity *userActivity;
/*!
@note Must be initilaized with either an intent or user activity, using those initializers.
*/
+ (instancetype)new NS_UNAVAILABLE;
/*!
@note Must be initilaized with either an intent or user activity, using those initializers.
*/
- (instancetype)init NS_UNAVAILABLE;
/*!
@abstract Creates a shortcut with the given intent.
@param intent Must have a title and have valid shortcut types.
@return Will return @c nil (and log an error) if the intent isn't valid.
*/
- (nullable instancetype)initWithIntent:(INIntent *)intent;
/*!
@abstract Creates a shortcut with the given user activity.
*/
- (instancetype)initWithUserActivity:(NSUserActivity *)userActivity;
@end
INShortcut
提供了两种模型,可以通过Siri和APP中进行接收和传递相关消息。
NSUserActivity | Intents |
---|---|
需要打开app进行操作时使用 | 需要在Siri界面直接操作时使用 |
仅仅表示在Spotlight中的索引项目时 | 需要对操作添加自定义短语或自定义UI时 |
Siri建议的颗粒度较大 | Siri会根据不同情况给出相对精确的建议 |
NSUserActivity使用方法:
先在项目的 plist 文件里定义 属性为 Array 的 NSUserActivityTypes
,为其添加对应的属性值,比如:"com.xxxx.xxxx-sports"
。
然后在需要弹出添加捷径的页面试下下放代码即可:
- (void)gotoAddCustomVoiceShortcutView {
NSUserActivity *activity = [self donateSportActivity];
INShortcut *shortcut = [[INShortcut alloc] initWithUserActivity:activity];
INUIAddVoiceShortcutViewController *vc = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortcut];
vc.delegate = self;
[self presentViewController:vc animated:YES completion:^{
}];
}
//此方法返回一个 NSUserActivity 对象。
- (NSUserActivity *)donateSportActivity {
NSUserActivity *checkInActivity = [[NSUserActivity alloc] initWithActivityType:@"com.xxxx.xxxxxx"];
checkInActivity.eligibleForSearch = YES;
if (@available(iOS 12.0, *)) {
checkInActivity.eligibleForPrediction = YES;
checkInActivity.suggestedInvocationPhrase = @"我回家了";//搜索的关键字
}
checkInActivity.title = @"执行场景";
checkInActivity.contentDescription = @"开客厅灯,关窗帘,语音播报今天的新闻";
return checkInActivity;
}
效果如下:
然后实现INUIAddVoiceShortcutViewController
的两个delegate
方法,分别处理取消和完成两个事件
#pragma mark - INUIAddVoiceShortcutViewControllerDelegate
- (void)addVoiceShortcutViewControllerDidCancel:(INUIAddVoiceShortcutViewController *)controller API_AVAILABLE(ios(12.0)){
[controller dismissViewControllerAnimated:YES completion:nil];
}
- (void)addVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)controller didFinishWithVoiceShortcut:(INVoiceShortcut *)voiceShortcut error:(NSError *)error API_AVAILABLE(ios(12.0)){
// 处理业务逻辑
[controller dismissViewControllerAnimated:YES completion:nil];
}
PS:如果是修改Siri指令,直接把目标 vc 换成 INUIEditVoiceShortcutViewController
即可。
当然这里有还有一个问题,如何判断用户是否已经添加了语音短语,从而确定去选择 add or edit ?
Intent
早已为我们准备好该方法,拿到结果后,遍历判断就好。
需要注意的是,该方法是不在主线程中执行,所以完成后,如果需要更新UI,请手动回到主线程。
[[INVoiceShortcutCenter sharedCenter] getAllVoiceShortcutsWithCompletion:^(NSArray * _Nullable voiceShortcuts, NSError * _Nullable error) {
}];
接着在appDelegate
里面去实现下面方法,用来处理用户通过Siri短语或者系统只能提示启动我们APP后的事件处理:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler{
if (@available(iOS 12.0, *)) {
if([userActivity.interaction.intent isKindOfClass:[LHSceneIntent class]]){
LHLogInfo(@"*** shortCut 进入APP");
} else {
if ([userActivity.activityType isEqualToString: @"com.xxxx.xxxxx"]) {
LHLogInfo(@"*** shortCut 进入APP");
}
}
} else {
// Fallback on earlier versions
}
return YES;
}
Siri
ShortCuts
还有一个 Extension
的功能,可以在Shortcut
里面添加APP的一些操作,或者通过Siri界面直接执行一些操作(这才是iOS12 捷径真正方便强大的功能)。 我们下篇再讲