MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Objective-C中的SiriKit语音指令集成

2022-12-046.5k 阅读

SiriKit概述

SiriKit是苹果公司提供的一套框架,允许开发者将Siri语音交互功能集成到自己的应用程序中。通过SiriKit,用户能够使用自然语言与Siri进行交互,从而执行与应用相关的特定任务,极大地提升了用户体验,特别是在双手忙碌或不方便操作设备的场景下。

SiriKit基于Intents框架,它定义了一系列标准的意图(Intent),这些意图代表了用户可能想要执行的操作类型。例如,导航到某个地点(导航类意图)、发送信息(通信类意图)、查询锻炼记录(健身类意图)等。开发者的任务就是根据应用的功能,适配这些标准意图,并提供相应的处理逻辑。

SiriKit的优势

  1. 提高用户参与度:语音交互为用户提供了更加便捷的操作方式,使得用户在无需手动操作设备的情况下就能完成任务,特别是在驾车、运动等场景下,显著提高了用户与应用的交互频率。
  2. 增强应用曝光度:支持SiriKit的应用在搜索结果和Siri建议中更具优势,能够获得更多的展示机会,有助于吸引新用户。
  3. 提升用户满意度:提供流畅的语音交互体验,符合现代用户对高效、便捷操作的期望,从而提升用户对应用的满意度和忠诚度。

SiriKit的应用场景

  1. 导航应用:用户可以通过Siri语音指令告诉导航应用目的地,应用根据意图规划路线并开始导航。
  2. 通信应用:如发送短信、拨打电话、发起视频通话等操作,用户无需手动输入联系人或点击按钮,直接通过语音指令即可完成。
  3. 健身应用:用户可以询问健身应用关于自己的锻炼历史、设定锻炼目标等,应用根据意图提供相应的信息或执行相关操作。

在Objective-C项目中集成SiriKit的准备工作

1. 检查项目支持的iOS版本

SiriKit从iOS 10开始支持,因此确保你的项目部署目标为iOS 10或更高版本。在Xcode项目设置中,找到“General”选项卡,在“Deployment Info”部分确认“iOS Deployment Target”为合适的版本。

2. 配置项目权限

要使用SiriKit,需要在项目的Info.plist文件中添加相关权限。打开项目的Info.plist文件,添加以下权限:

<key>NSSiriUsageDescription</key>
<string>$(PRODUCT_NAME) uses Siri to send messages on your behalf</string>

上述代码中,<string>内的内容是向用户解释应用使用Siri的目的,你可以根据实际应用功能进行修改。

3. 导入必要的框架

在Objective-C项目中,需要导入Intents和IntentsUI框架。在需要使用SiriKit功能的源文件中,添加以下导入语句:

#import <Intents/Intents.h>
#import <IntentsUI/IntentsUI.h>

定义SiriKit意图

1. 选择合适的意图类型

SiriKit提供了多种预定义的意图类型,根据应用功能选择合适的意图。例如,如果你的应用是一个待办事项应用,可能会选择INCreateTaskIntent(创建任务意图)、INDeleteTaskIntent(删除任务意图)等。以下以创建任务意图为例进行说明。

2. 创建意图处理类

创建一个继承自INIntentHandling协议的类来处理意图。以处理INCreateTaskIntent为例,创建一个TaskIntentHandler类:

#import <Foundation/Foundation.h>
#import <Intents/Intents.h>

@interface TaskIntentHandler : NSObject <INCreateTaskIntentHandling>

@end

@implementation TaskIntentHandler

// 处理创建任务意图
- (void)handleCreateTask:(INCreateTaskIntent *)intent
              completion:(void (^)(INCreateTaskIntentResponse *response))completion {
    // 这里编写处理创建任务的逻辑
    NSString *taskTitle = intent.taskTitle;
    if (taskTitle) {
        // 假设这里有一个创建任务的方法
        BOOL success = [self createTaskWithTitle:taskTitle];
        if (success) {
            INCreateTaskIntentResponse *response = [[INCreateTaskIntentResponse alloc] initWithCode:INCreateTaskIntentResponseCodeSuccess userActivity:nil];
            completion(response);
        } else {
            INCreateTaskIntentResponse *response = [[INCreateTaskIntentResponse alloc] initWithCode:INCreateTaskIntentResponseCodeFailure userActivity:nil];
            completion(response);
        }
    } else {
        INCreateTaskIntentResponse *response = [[INCreateTaskIntentResponse alloc] initWithCode:INCreateTaskIntentResponseCodeInvalidParameters userActivity:nil];
        completion(response);
    }
}

// 模拟创建任务的方法
- (BOOL)createTaskWithTitle:(NSString *)title {
    // 实际应用中这里会与数据存储等交互
    NSLog(@"Creating task with title: %@", title);
    return YES;
}

@end

3. 注册意图处理类

在应用的AppDelegate中注册意图处理类。在application:didFinishLaunchingWithOptions:方法中添加以下代码:

#import "TaskIntentHandler.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    INInteraction *interaction = [launchOptions valueForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
    if ([interaction.intent isKindOfClass:[INCreateTaskIntent class]]) {
        TaskIntentHandler *handler = [[TaskIntentHandler alloc] init];
        [handler handleCreateTask:(INCreateTaskIntent *)interaction.intent completion:^(INCreateTaskIntentResponse * _Nonnull response) {
            INInteractionResponse *interactionResponse = [[INInteractionResponse alloc] initWithIntentResponse:response];
            [interaction respondWith:interactionResponse completion:nil];
        }];
    }
    return YES;
}

配置SiriKit意图界面(可选)

如果希望为SiriKit意图提供自定义界面,可以使用IntentsUI框架。

1. 创建意图UI扩展

在Xcode中,选择“File” -> “New” -> “Target”,然后选择“Intents UI Extension”。按照向导完成扩展的创建。

2. 配置意图UI扩展

在意图UI扩展的Info.plist文件中,配置支持的意图类型。例如,对于INCreateTaskIntent,添加以下内容:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>IntentsSupported</key>
        <array>
            <string>INCreateTaskIntent</string>
        </array>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.intents.ui.services</string>
</dict>

3. 创建自定义意图UI视图控制器

在意图UI扩展中,创建一个继承自INUIHostedViewControlling协议的视图控制器。例如:

#import <UIKit/UIKit.h>
#import <IntentsUI/IntentsUI.h>

@interface TaskIntentUIViewController : UIViewController <INUIHostedViewControlling>

@end

@implementation TaskIntentUIViewController

- (void)configureWithInteraction:(INInteraction *)interaction context:(INUIHostedViewContext)context completion:(void (^)(CGSize))completion {
    // 这里根据意图配置自定义界面
    if ([interaction.intent isKindOfClass:[INCreateTaskIntent class]]) {
        INCreateTaskIntent *intent = (INCreateTaskIntent *)interaction.intent;
        NSString *taskTitle = intent.taskTitle;
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 200, 30)];
        label.text = [NSString stringWithFormat:@"Creating task: %@", taskTitle];
        [self.view addSubview:label];
    }
    completion(CGSizeMake(320, 200));
}

@end

4. 注册自定义意图UI视图控制器

在意图UI扩展的INUIHostedViewService类中,注册自定义视图控制器。在- (UIViewController *)viewControllerForIntent:(INIntent *)intent withContext:(INUIHostedViewContext)context completion:(void (^)(CGSize))completion方法中添加以下代码:

#import "TaskIntentUIViewController.h"

- (UIViewController *)viewControllerForIntent:(INIntent *)intent withContext:(INUIHostedViewContext)context completion:(void (^)(CGSize))completion {
    TaskIntentUIViewController *viewController = [[TaskIntentUIViewController alloc] init];
    [viewController configureWithInteraction:[[INInteraction alloc] initWithIntent:intent response:nil] context:context completion:completion];
    return viewController;
}

测试SiriKit集成

1. 在模拟器中测试

在Xcode中,选择一个支持Siri的模拟器(如iPhone 7 Plus或更高,且运行iOS 10或更高版本)。运行应用后,长按Home键(模拟器中通过快捷键Command + Space)唤起Siri,然后尝试说出与配置的意图相关的语音指令。例如,对于前面配置的创建任务意图,可以说“使用[应用名称]创建一个任务,任务名为学习Objective-C”。

2. 在真机上测试

将设备连接到Xcode,确保设备运行iOS 10或更高版本且已开启Siri功能。运行应用后,同样通过长按Home键(iPhone X及以上通过长按侧边按钮)唤起Siri,测试语音指令。

在测试过程中,注意观察控制台输出,查看意图处理过程中是否有错误或异常。如果意图处理失败,根据返回的INCreateTaskIntentResponseCode判断失败原因,如INCreateTaskIntentResponseCodeInvalidParameters表示参数无效,需要检查意图参数的获取和处理逻辑。

处理复杂意图和多意图场景

1. 处理复杂意图

有些意图可能包含多个参数和复杂的逻辑。例如,INSendMessageIntent不仅需要接收者信息,还可能包含消息内容、附件等。在处理这类意图时,要仔细解析意图的各个属性。

INSendMessageIntent为例,处理类如下:

#import <Foundation/Foundation.h>
#import <Intents/Intents.h>

@interface MessageIntentHandler : NSObject <INSendMessageIntentHandling>

@end

@implementation MessageIntentHandler

- (void)handleSendMessage:(INSendMessageIntent *)intent
               completion:(void (^)(INSendMessageIntentResponse *response))completion {
    NSArray<INPerson *> *recipients = intent.recipients;
    NSString *messageContent = intent.content;
    if (recipients && messageContent) {
        // 处理发送消息逻辑,这里假设一个发送消息的方法
        BOOL success = [self sendMessage:messageContent toRecipients:recipients];
        if (success) {
            INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:nil];
            completion(response);
        } else {
            INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeFailure userActivity:nil];
            completion(response);
        }
    } else {
        INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc] initWithCode:INSendMessageIntentResponseCodeInvalidParameters userActivity:nil];
        completion(response);
    }
}

// 模拟发送消息的方法
- (BOOL)sendMessage:(NSString *)message toRecipients:(NSArray<INPerson *> *)recipients {
    // 实际应用中这里会与消息发送服务交互
    NSLog(@"Sending message: %@ to %@", message, recipients);
    return YES;
}

@end

2. 多意图场景

一个应用可能支持多种意图。在AppDelegate中,需要对不同的意图进行分别处理。例如,同时支持创建任务意图和发送消息意图:

#import "TaskIntentHandler.h"
#import "MessageIntentHandler.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    INInteraction *interaction = [launchOptions valueForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
    if ([interaction.intent isKindOfClass:[INCreateTaskIntent class]]) {
        TaskIntentHandler *handler = [[TaskIntentHandler alloc] init];
        [handler handleCreateTask:(INCreateTaskIntent *)interaction.intent completion:^(INCreateTaskIntentResponse * _Nonnull response) {
            INInteractionResponse *interactionResponse = [[INInteractionResponse alloc] initWithIntentResponse:response];
            [interaction respondWith:interactionResponse completion:nil];
        }];
    } else if ([interaction.intent isKindOfClass:[INSendMessageIntent class]]) {
        MessageIntentHandler *handler = [[MessageIntentHandler alloc] init];
        [handler handleSendMessage:(INSendMessageIntent *)interaction.intent completion:^(INSendMessageIntentResponse * _Nonnull response) {
            INInteractionResponse *interactionResponse = [[INInteractionResponse alloc] initWithIntentResponse:response];
            [interaction respondWith:interactionResponse completion:nil];
        }];
    }
    return YES;
}

优化SiriKit集成的用户体验

1. 提供清晰的语音指令引导

在应用内或帮助文档中,提供清晰的语音指令示例,告知用户如何使用Siri与应用进行交互。例如,在待办事项应用中,可以提示用户“你可以说‘使用[应用名称]创建一个任务,任务名为购物’来创建新任务”。

2. 及时反馈处理结果

在意图处理完成后,通过Siri向用户反馈处理结果。例如,对于创建任务意图,如果任务创建成功,Siri可以回复“任务已成功创建”;如果失败,可以回复“任务创建失败,请检查输入信息”。

3. 处理语音识别错误

语音识别可能会出现错误,当识别到的意图参数不准确时,应用应能够向用户提示正确的输入方式。例如,对于发送消息意图,如果识别的接收者信息有误,可以提示“未找到该联系人,请确认联系人姓名或号码”。

常见问题及解决方法

1. Siri不识别应用的语音指令

  • 原因:可能是应用未正确注册意图处理类,或者Info.plist中的权限配置有误。
  • 解决方法:检查AppDelegate中意图处理类的注册代码是否正确,确保Info.plist中NSSiriUsageDescription权限配置正确且描述清晰。

2. 意图处理失败

  • 原因:可能是意图参数解析错误,或者处理逻辑中出现异常。
  • 解决方法:在意图处理类中添加详细的日志输出,检查意图参数是否正确获取,以及处理逻辑(如创建任务、发送消息等方法)是否正常执行。

3. 自定义意图UI不显示

  • 原因:可能是意图UI扩展配置有误,或者视图控制器未正确注册。
  • 解决方法:检查意图UI扩展的Info.plistIntentsSupported配置是否正确,以及INUIHostedViewService类中视图控制器的注册代码是否准确。

通过以上步骤和方法,你可以在Objective-C项目中成功集成SiriKit语音指令功能,为用户提供更加便捷、高效的语音交互体验,使应用在竞争激烈的移动应用市场中脱颖而出。在实际开发过程中,要不断测试和优化,以确保SiriKit功能的稳定性和可靠性。