【发布时间】:2022-01-07 14:58:56
【问题描述】:
自定义 Intent 的 Objective-C 实现中的 IntentHandler 无法接收来自语音激活快捷方式的呼叫。当使用 Siri 调用捐赠的交互时,我观察到我在控制台应用程序中收到以下错误,声称意图的意图处理程序方法未实现:
-[INIntentDeliverer _invokeIntentHandlerMethodForIntent:intentHandler:parameterNamed:keyForSelectors:executionHandler:unimplementedHandler:] _invokeIntentHandlerMethodForIntent sirikit.intent.voice_commands.RunVoiceCommandIntent
-[WFRVCIntentHandler stateMachineForIntent:] Created state machine <WFRVCStateMachine: 0x102e23970 state=WaitingForServer phase=Unknown> for intent with identifier 8A87FC68-329D-49FF-B534-B0A5821854CA
-[INIntentDeliverer _invokeIntentHandlerMethodForIntent:intentHandler:parameterNamed:keyForSelectors:executionHandler:unimplementedHandler:] _invokeIntentHandlerMethodForIntent sirikit.intent.voice_commands.RunVoiceCommandIntent
此错误与尝试使用语音命令触发自定义意图导致 iOS 调用我的 appDelegate,特别是 application:continueUserActivity:restorationHandler: 的事实一致。根据文档,只有在未处理意图且必须由主应用程序处理时才应调用 restoreHandler。
由于 Objective-C 实现的文档很少,我无法弄清楚我缺少什么。我试图将 Siri Shortcuts 的示例 SoupChef 应用程序实现映射到我的实现。我无法弄清楚我哪里出错了。这是我的实现(对不起所有细节,但我希望你能看到一些错误):
首先,我实现了两个额外的目标;一个共享框架和一个意图扩展。我还实现了一个意图定义文件。
这是我的目标的图像:
W_P_r是主app,W_P_rKit是共享框架,PartsListManagerIntents是Intents Extension。
接下来,这是我的 Intents 定义文件和它所属的目标成员:
我还为 main 目标和 PartsListIntentManager 目标添加了一个应用组到 add 的功能部分。我在主要目标中添加了 Siri 功能。
所有这些都会自动创建一些代码,包括默认的 IntentHandler.m 和 PartsListManagerIntents 目标中的 info.plist。我已将 info.plist 更新如下:
这是自动生成的 IntentHandler(我已对其进行修改以记录活动并调用驻留在 W_P_rKit 共享框架中的特定意图处理程序:
#import "IntentHandler.h"
#import <Intents/Intents.h>
#import <W_P_rKit/W_P_rKit.h>
#import "CreatePartsListIntentHandler.h"
#import "P__tHandler.h"
#import <os/log.h>
@interface IntentHandler () /* <CreatePartsListIntentHandling, P__tHandling> */
@end
@implementation IntentHandler
- (id)handlerForIntent:(INIntent *)intent {
os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG, "handlerForIntent: Reached IntentHandler.");
if ([intent.identifier isEqualToString:@"P__rIntent"]) {
NSLog(@"P__rIntent");
return [[P__rIntentHandler alloc] init];
}
else if ([intent.identifier isEqualToString:@"CreatePartsListIntent"]) {
NSLog(@"CreatePartsListIntent");
os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG, "handlerForIntent: IntentHandler Received CreatePartsListIntent.");
return [[CreatePartsListIntentHandler alloc] init];
}
return self;
}
请注意,CreatePartsListIntentHandler 是一个实现 CreatePartsListIntentHandling 协议(IntentHandler 的解析、确认和处理方法)的类。
下面是应该触发 iOS 调用 IntentHandler 的相关实现:
在我的应用程序中,当用户填写新项目的名称时,我拨打电话以捐赠互动,如下所示:
CreatePartsListIntent *data = [[CreatePartsListIntent alloc] init];
data.projectName = [projectPlistName copy];
data.quantity = [NSNumber numberWithInteger : currentProjectQuantity];
[[W_P_rDonationManager sharedInstance] donateCreatePartsListIntent : data];
对 donateCreatePartsListIntent 的调用执行以下操作:
data.suggestedInvocationPhrase = @"Create Parts List";
INInteraction* interaction = [[INInteraction alloc] initWithIntent:data response:nil];
[interaction donateInteractionWithCompletion:^(NSError * _Nullable error) { ... }
一旦用户创建了空的部件列表(强制进行上述交互捐赠),视图控制器 将显示一个“添加 Siri 快捷方式”按钮。自动点击按钮 调用如下方法创建快捷方式:
-(void) addCreatePartsListShortcutWasTapped {
CreatePartsListIntent *intentWithData = [[WoodPickerDonationManager sharedInstance] prepareCreatePartsListIntent :
@"" withNumberOfAssemblies : 1];
INShortcut *shortcut = [[INShortcut alloc] initWithIntent:intentWithData];
INUIAddVoiceShortcutViewController *addSiri = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortcut];
addSiri.delegate = self;
[self presentViewController:addSiri animated:YES completion: nil];
}
对 prepareCreatePartsListIntent 的调用执行以下操作:
-(CreatePartsListIntent *) prepareCreatePartsListIntent : (NSString *) partsListName withNumberOfAssemblies : (NSInteger) quantity {
CreatePartsListIntent *intentWithData = [[CreatePartsListIntent alloc] init];
intentWithData.projectName = partsListName;
intentWithData.quantity = [NSNumber numberWithInteger: quantity];
intentWithData.suggestedInvocationPhrase = @"Create Parts List";
return intentWithData;
}
这确实会创建一个快捷方式应用程序中可见的快捷方式。单击快捷方式或说出调用短语将带您 直接到应用委托的 application:userActivity:restorationHandler。但它不调用 IntentHandler。
为什么我的 IntentHandler 没有被调用?为什么iOS会发送错误消息_invokeIntentHandlerMethodForIntent:intentHandler:parameterNamed:keyForSelectors:executionHandler:unimplementedHandler:?
实际上我已经为此苦苦挣扎了好几个星期。任何帮助或提示都会很有帮助。
【问题讨论】:
-
我在构建实现时记录了很多内容。也许这会有所帮助? pqvst.com/2018/09/21/…
-
@pqvst 是的,这是一篇很好的文章,这就是我联系你的原因。我想知道你在那篇文章中所说的一件事。您能否详细说明您在编写时遇到的问题: 3)将 Intents 定义文件添加到您的 Intents 扩展目标。注意:我尝试将意图定义文件移动到主应用程序和意图扩展都可以访问的共享 Cocoa Touch 框架,但这似乎不起作用。因此,我建议将意图定义文件保留在主应用程序目标中,并将意图目标添加到目标成员资格设置中。
-
Tbh,我不记得了,因为它已经有几年了,但我想如果 Intents 定义文件不在主应用程序中,我会遇到编译错误。总的来说,我记得有很多问题。一般来说,我发现删除所有保存的快捷方式、重新安装应用程序以及从头开始在很多情况下都有帮助。
-
当您接到
application:continueUserActivity:restorationHandler:的电话时,activity.interaction.intent是否已填充? -
@davidgyoung 在 Xcode 控制台中,interaction.intent 参数自动完成(即显示该参数存在。但是当我尝试打印此内容时,出现以下错误:错误:
:1:14: 在'NSUserActivity *' userActivity.interaction.intent 类型的对象上找不到属性'interaction'。你认为为什么会这样?如果我打印 userActivity.activityType,它会打印我的意图“CreatePartsListIntent”,所以它知道我的意图。
标签: objective-c sirishortcuts intents-extension inshortcut