我的自定义意图的 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 是主应用程序,W_P_rKit 是共享框架,PartsListManagerIntents 是 Intents 扩展。
接下来,这是我的 Intents 定义文件和它所属的目标成员:
我还在 main 目标和 PartsListIntentManager 目标的 add 的功能部分中添加了一个应用程序组。我将 Siri 功能添加到主要目标。
所有这些都会自动创建一些代码,包括 PartsListManagerIntents 目标中的默认 IntentHandler.m 和 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:?
实际上,我已经为此苦苦挣扎了好几个星期。任何帮助或提示都会很有帮助。