Arclin

Advocate Technology. Enjoy Technology.

0%

iOS12 新玩具ShortCut(捷径)使用

介绍

升级iOS12之后可以在设置-Siri与搜索 中发现一个 捷径 功能, 所谓ShortCut就是其英文翻译
其作用就是让用户自定义一个一句话或者短语, 然后可以触发app做一系列动作

接入

ShortCut分为两种, 一种是在手机的Spotlight上搜索某个关键字的时候可以搜索到你的app, 这个关键字就是ShortCut的一种(文字输入), 你需要使用NSUserActivity去实现这个功能

依赖 CoreSpotlight CoreServices

另外一种叫做 Intent(语音输入), 需要添加一个IntentExtension和IntentExtensionUI, 然后在主Target添加一个intentdefinition文件, 详细的配置大家可以参考
文章1
文章2

依赖Intents IntentsUI

最简单的配置操作步骤

  1. 项目的Capabilities打开Siri

  2. 授权

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    if (@available(iOS 10.0, *)) {
    [INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) {
    switch (status) {
    case INSiriAuthorizationStatusNotDetermined:
    NSLog(@"用户尚未对该应用程序作出选择。");
    break;
    case INSiriAuthorizationStatusRestricted:
    NSLog(@"此应用程序无权使用Siri服务");
    break;
    case INSiriAuthorizationStatusDenied:
    NSLog(@"用户已明确拒绝此应用程序的授权");
    break;
    case INSiriAuthorizationStatusAuthorized:
    NSLog(@"用户可以使用此应用程序的授权");
    break;
    default:
    break;
    }
    }];
    }
    • 新建一个intentdefinition,比如A.intentdefinition
    • 新建一个Target,Intent Extension有需要的话把Intent UI Extension也加上,General中配置相关证书
    • 进入A.intentdefinition,界面左下角+号点一下,点击new intent
    • 界面右边Target Membership,把步骤2中新增的Target给勾上
    • 界面中间Title填写需要展示的标题,Descripion 写描述
    • Build一下,系统自动生成头文件,头文件名字在界面右测的导航页的第三个按钮的Custom Class
    • 找个控制器,导入步骤8生成的头文件,添加个按钮,比如
    1
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"捷径" style:UIBarButtonItemStylePlain target:self action:@selector(siri:)];
  3. 点击按钮召唤添加Shortcut的控制器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    - (void)siri:(UIBarButtonItem *)item {
    if (@available(iOS 12.0, *)) {
    // 这个类名具体看你生成了叫什么名字的头文件
    ZeRiIntent *intent = [[ZeRiIntent alloc] init];
    intent.suggestedInvocationPhrase = @"打开xxx"; // 引导用户说的语句
    INShortcut *shortCur = [[INShortcut alloc] initWithIntent:intent];
    INUIAddVoiceShortcutViewController *vc = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortCur];
    vc.delegate = self;
    [self presentViewController:vc animated:YES completion:nil];
    } else {
    // Fallback on earlier versions
    }
    }
  4. 同个地方实现代理方法

    1
    2
    3
    4
    5
    6
    7
    #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];
    }
  5. 进入Intent target中的IntentHandler类,导入步骤8生成的头文件,要是头文件找不到,在这个target的info.plistNSExtension下的IntentsSupported下添加一个名为那个头文件的值,主target的info.plistNSUserActivityTypes下也加一个一样的

  6. IntentHandler.m遵循协议XXXIntentHandling(具体协议名看你的类名),实现两个方法

    1
    2
    3
    4
    5
    6
    7
    8
    	// 用户说了那句话之后要Siri做什么事情
    - (void)handleZeRiIntent:(ZeRiIntent *)intent completion:(void (^)(ZeRiIntentResponse * _Nonnull))completion {
    completion([[ZeRiIntentResponse alloc] initWithCode:ZeRiIntentResponseCodeContinueInApp userActivity:nil]);
    }
    // 用户确认了之后要Siri做什么事情
    - (void)confirmZeRiIntent:(ZeRiIntent *)intent completion:(void (^)(ZeRiIntentResponse * _Nonnull))completion {
    completion([[ZeRiIntentResponse alloc] initWithCode:ZeRiIntentResponseCodeContinueInApp userActivity:nil]);
    }

    ZeRiIntentResponseCodeContinueInApp只是枚举中其中一个值,使用不同的值会有不同 效果,自己探索一下,这里的值指的是打开app(具体方法名看协议)

  7. 进入AppDelegate,实现方法如下,根据Intent类名判断用户想要的操作

    1
    2
    3
    4
    5
    	- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
    if ([userActivity.activityType isEqualToString:@"XXXIntent"]) {
    }
    return YES;
    }
  8. 结束