Objective c NSSpeechRecognizer和.delegate=self;问题

Objective c NSSpeechRecognizer和.delegate=self;问题,objective-c,macos,speech-recognition,osx-elcapitan,appkit,Objective C,Macos,Speech Recognition,Osx Elcapitan,Appkit,我在做这件事时遇到了一个问题,事实证明这是一个障碍。我在El Capitan上玩苹果的NSSpeechRecognitizer软件,我试图让这个家伙正常运行,这样当我给它的谜语呈现给用户时,用户可以用一个词来回应“做些酷的事”。目前,委托方法: -(void) speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command { ... }` 即使识别图标似乎正确地检测到谜语的答案,也从未

我在做这件事时遇到了一个问题,事实证明这是一个障碍。我在El Capitan上玩苹果的
NSSpeechRecognitizer
软件,我试图让这个家伙正常运行,这样当我给它的谜语呈现给用户时,用户可以用一个词来回应“做些酷的事”。目前,委托方法:

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

即使识别图标似乎正确地检测到谜语的答案,也从未调用。

问题在于您的
main
函数有一个循环,不断检查语音是否已被识别。您没有给
NSSpeechRecognizer
一个向您实际发送任何消息的机会

你的应用程序需要让主“运行循环”运行,这样它才能传递消息。通常,在OSX应用程序中,您的
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;
}
长期的解决办法是将代码移出
main
,并像真正的OSX应用程序一样构建它。与使用循环轮询条件(如
recognizerDelegate.didRecognite
)不同,您可以直接从委托方法(如
-speechRecognizer:didRecognitizeCommand:
)触发“下一件事”,或者使用
NSTimer
定期运行代码


有关更多详细信息,请参阅Apple文档,特别是“主事件循环”部分。

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

func speechRecognizer(_ sender: NSSpeechRecognizer,
                      didRecognizeCommand command: String) {}
…从未被呼叫过,尽管一切似乎都在运行

为了让代码正常工作,我改变了三件事

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

。。。我也做了另外两件事

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


3) 我在info.pList中添加了“Privacy-Speech Recognition Usage Description”,并将字符串值设置为“I want down what you say”

请在问题中包含代码的相关部分。在您链接到的github存储库中,我没有看到任何使用
NSSpeechRecognizer
的内容。(唯一的代码是main.m,它直接来自Xcode模板。)你完全正确。很抱歉。哇,非常感谢你的详细解释。我真的需要更清楚地了解运行循环内部的存在是如何影响对象的。我想我的下一步是学习如何重新组织一切,这样我就可以简单地
返回NSApplicationMain(…)主菜单的内部。我希望能够做到这一点,而不必依赖XCode为我设置它(在vim内部,如果更好的话:P),这就是为什么我首先遇到这个问题的原因!无论如何-谢谢你,现在一切都很好。@DavidLewis:太好了!由于您发现此答案很有用,请单击答案旁边的复选标记。
func speechRecognizer(_ sender: NSSpeechRecognizer,
                      didRecognizeCommand command: String) {}