NSSpeechRecognizer 和 .delegate=self;问题
NSSpeechRecognizer and .delegate=self; Problems
我运行遇到了这个little Objective-C project我正在做的问题,事实证明这是一个障碍。我正在 El Capitan 上玩 Apple 的 NSSpeechRecognizer
软件,我正试图让这个人 运行 正确地玩,这样当我给它的谜语被提出给用户时,用户可以用一句话回应 "do something cool"。就目前而言,委托方法:
-(void) speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command { ... }`
甚至从未被调用过,即使识别图标看起来正确地检测到了谜语的答案。
问题是您的 main
函数有一个循环,不断检查语音是否已被识别。您没有给 NSSpeechRecognizer
实际向您发送任何消息的机会。
您的应用需要让主要 "run loop" 运行,以便它可以传递消息。通常,在 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)有机会做任何事情。所以,什么也没有发生。
要在短期内解决此问题:您可以让主 运行 循环 运行 在每个循环中运行一小会儿。此代码会让系统 运行 一秒钟,然后 return 到您的代码,因此您可以再次检查:
while (recognizerDelegate.didRecognize == NO) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}
长期的解决方法是将您的代码移出 main
并将其构造为真正的 OS X 应用程序。不是使用循环来轮询 recognizerDelegate.didRecognize
之类的条件,而是直接从 -speechRecognizer:didRecognizeCommand:
之类的委托方法中触发 "next thing",或者使用 NSTimer
之类的方法 运行 定期编码。
有关详细信息,请参阅 Apple 文档 Cocoa Application Competencies for OS X,特别是 "Main Event Loop" 部分。
我在使用 NSSpeechRecognizer 时遇到了同样的问题。回调函数:
func speechRecognizer(_ sender: NSSpeechRecognizer,
didRecognizeCommand command: String) {}
...从未被调用,尽管一切似乎都在工作。
为了让代码正常工作,我改变了三件事。
1) 我必须在我的 "sandboxed" 模式应用程序中启用权利以允许使用麦克风。
...我也做了另外两件事
2) 我在info.pList中添加了"Privacy - Microphone Usage Description",并将字符串值设置为"I want to listen to you speak"
3) 我在info.pList中添加了"Privacy - Speech Recognition Usage Description",并将字符串值设置为"I want to write down what you say"
我运行遇到了这个little Objective-C project我正在做的问题,事实证明这是一个障碍。我正在 El Capitan 上玩 Apple 的 NSSpeechRecognizer
软件,我正试图让这个人 运行 正确地玩,这样当我给它的谜语被提出给用户时,用户可以用一句话回应 "do something cool"。就目前而言,委托方法:
-(void) speechRecognizer:(NSSpeechRecognizer *)sender didRecognizeCommand:(NSString *)command { ... }`
甚至从未被调用过,即使识别图标看起来正确地检测到了谜语的答案。
问题是您的 main
函数有一个循环,不断检查语音是否已被识别。您没有给 NSSpeechRecognizer
实际向您发送任何消息的机会。
您的应用需要让主要 "run loop" 运行,以便它可以传递消息。通常,在 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)有机会做任何事情。所以,什么也没有发生。
要在短期内解决此问题:您可以让主 运行 循环 运行 在每个循环中运行一小会儿。此代码会让系统 运行 一秒钟,然后 return 到您的代码,因此您可以再次检查:
while (recognizerDelegate.didRecognize == NO) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}
长期的解决方法是将您的代码移出 main
并将其构造为真正的 OS X 应用程序。不是使用循环来轮询 recognizerDelegate.didRecognize
之类的条件,而是直接从 -speechRecognizer:didRecognizeCommand:
之类的委托方法中触发 "next thing",或者使用 NSTimer
之类的方法 运行 定期编码。
有关详细信息,请参阅 Apple 文档 Cocoa Application Competencies for OS X,特别是 "Main Event Loop" 部分。
我在使用 NSSpeechRecognizer 时遇到了同样的问题。回调函数:
func speechRecognizer(_ sender: NSSpeechRecognizer,
didRecognizeCommand command: String) {}
...从未被调用,尽管一切似乎都在工作。
为了让代码正常工作,我改变了三件事。
1) 我必须在我的 "sandboxed" 模式应用程序中启用权利以允许使用麦克风。
...我也做了另外两件事
2) 我在info.pList中添加了"Privacy - Microphone Usage Description",并将字符串值设置为"I want to listen to you speak"
3) 我在info.pList中添加了"Privacy - Speech Recognition Usage Description",并将字符串值设置为"I want to write down what you say"