NSSpeechRecognizer和.delegate=self; 出现问题

3

我在做一个Objective-C小项目时遇到了问题,这个项目的地址是https://github.com/lewisinc/DoorOfDurin,问题有点棘手。我正在尝试在El Capitan上使用Apple的NSSpeechRecognizer软件,并且我正在尝试让它正确运行,以便当我给用户提出谜语时,用户可以回答一个单词来"做一些酷炫的事情"。目前,代理方法的状态如下:

-(void) speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command { ... }`

尽管识别图标正确检测到了谜底,但它甚至没有被调用。

1
请在您的问题中包含相关部分的代码。我没有看到您链接的Github存储库中使用NSSpeechRecognizer 的任何内容。(唯一的代码是main.m,它直接来自Xcode模板。) - Kurt Revis
你是绝对正确的。对此感到抱歉。 - David Lewis
2个回答

1
问题在于您的main函数中有一个循环,不断检查语音是否被识别。这样做会导致NSSpeechRecognizer无法向您传递任何消息。
您的应用程序需要让主“运行循环”运行,以便它可以传递消息。通常,在OS X应用程序中,您的main只需调用NSApplicationMain,该方法会为您处理此问题。
您的代码实际上是这样的:
@interface RecognizerDelegate : NSObject <NSSpeechRecognizerDelegate>

@property (nonatomic) NSSpeechRecognizer *recognizer;
@property (nonatomic) BOOL didRecognize;

@end

@implementation RecognizerDelegate

- (id)init
{
    if ((self = [super init])) {
        self.didRecognize = NO;

        self.recognizer = [[NSSpeechRecognizer alloc] init];
        self.recognizer.listensInForegroundOnly = NO;
        self.recognizer.blocksOtherRecognizers = YES;
        self.recognizer.delegate = self;
        self.recognizer.commands = @[ @"hello" ];
        [self.recognizer startListening];
    }

    return self;
}

- (void)speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command
{
    self.didRecognize = YES;
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        RecognizerDelegate *recognizerDelegate = [[RecognizerDelegate alloc] init];

        while (recognizerDelegate.didRecognize == NO) {
            // do nothing
        }

        NSLog(@"Recognized!");
    }

    return 0;
}

那个while循环没有任何有用的功能,只是在循环中运行你的CPU,浪费时间和能量。你没有让任何其他代码在NSSpeechSynthesizer或任何系统框架(如Foundation或AppKit)中有机会执行任何操作。所以什么也没发生。
为了在短期内修复这个问题:你可以让主运行循环在每次循环通过时运行一段时间。这段代码将让系统运行一秒钟,然后返回到你的代码,这样你就可以再次检查:
while (recognizerDelegate.didRecognize == NO) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}

长期的解决方法是将代码从main中移出,并像一个真正的OS X应用程序一样进行结构化。不要使用循环来轮询条件,如recognizerDelegate.didRecognize,而是直接从委托方法触发“下一个事情”,例如-speechRecognizer:didRecognizeCommand:,或者使用NSTimer定期运行代码。
有关更多详细信息,请参阅苹果文档Cocoa Application Competencies for OS X,特别是“主事件循环”部分。

哇,非常感谢您详细的解释。我真的需要更加注意现有运行循环对对象的影响。我想我的下一步是学习如何重新组织所有内容,以便我可以在主函数中简单地return NSApplicationMain(...);。我希望能够在不依赖XCode设置的情况下完成它(如果可能的话,在vim中完成:P),这也是我第一次遇到这个问题的原因!无论如何 - 谢谢,现在一切都很好。 - David Lewis
@DavidLewis:太好了!既然您觉得这个答案有用,请通过点击答案旁边的勾选标记接受它 - Kurt Revis

0

我在使用NSSpeechRecognizer时遇到了同样的问题。回调函数:

func speechRecognizer(_ sender: NSSpeechRecognizer,
                      didRecognizeCommand command: String) {}

尽管一切看起来都正常,但该函数从未被调用。

我改变了三件事情才让代码正常工作。

1)我必须在我的“沙盒”模式应用程序中启用授权,以允许使用麦克风。

... 我还做了另外两件事情。

2)我在info.pList中添加了“隐私-麦克风使用说明”,并将字符串值设置为“我想听你说话”

3)我在info.pList中添加了“隐私-语音识别使用说明”,并将字符串值设置为“我想记录下你说的话”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接