iOS12 Siri Shortcuts(一)

INShortcut

这是Shortcut开发中要实现的核心class,我们看下这个类所提供的api:

API_AVAILABLE(ios(12.0), watchos(5.0)) API_UNAVAILABLE(tvos)    API_UNAVAILABLE(macosx)
@interface INShortcut : NSObject <NSSecureCoding, NSCopying>

/*!
 @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中进行接收和传递相关消息。

image.png

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;
}

效果如下:


image.png

然后实现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<INVoiceShortcut *> * _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 捷径真正方便强大的功能)。 我们下篇再讲

推荐阅读更多精彩内容