我有一个类遍历OSX上给定文件夹的所有子文件夹,并为其找到的每个文件夹向其委托发送一条消息。
对于找到的每个文件夹,我想运行NSTask
。到现在为止还挺好。当我向terminationHandler
指定NSTask
时遇到问题。
这是代码:
-(void)crawler:(FTCFileSystemCrawler *)aCrawler
didFindFolder:(NSURL *)aURL
withName:(NSString *)aFileName
stop:(BOOL *)stop{
NSTask *task = [NSTask new];
task.launchPath = @"/usr/bin/say";
task.arguments = @[aFileName];
task.terminationHandler = ^(NSTask *aTask){
NSLog(@"Terminating!");
[self.tasks removeObject:aTask];
};
[self.tasks addObject:task];
[task launch];
//[task waitUntilExit];
}
这种方法很好,在将launch
发送到NSTask
之后,我发送了waitUntilExit
。如果不这样做,终止处理程序永远不会运行。
我做错了什么?
PS请记住,这只是一个简单的例子。我实际上是用这个来识别git repos并运行命令吧。
答案 0 :(得分:2)
你是否尝试过这样的事情,尽管使用task.terminationHandler = ^(NSTask *aTask)
可能是问题是在这个区域内使用但处理不当。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(taskDidTerminate:)
name:NSTaskDidTerminateNotification
object:nil];
答案 1 :(得分:1)
NSTask
一般来说使用起来非常棘手,使用不会在默认配置中输出任何文本的工具更是如此。正如您所发现的那样,waitUntilExit
将解决您的问题,但它会引发另一个问题,即它将在任务完成之前阻塞。解决此问题的一种常见方法是使用NSPipe
,如此答案[此处]所示。1尽管在Cocoa中有更好的方法!
根本不需要处理NSTask
,只需将Cocoa API用于语音引擎NSSpeechSynthesizer
即可。以下是转换后的相同代码的快速示例:
-(void)crawler:(FTCFileSystemCrawler *)aCrawler
didFindFolder:(NSURL *)aURL
withName:(NSString *)aFileName
stop:(BOOL *)stop{
NSSpeechSynthesizer *speechSynth = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
[speechSynth startSpeakingString:aFileName];
}
更简单的是,如果在谈话时仍需要回调,则可以使用speechSynthesizer:didFinishSpeaking:
委托方法。
答案 2 :(得分:1)
可能值得将task
存储到属性中以便保留它并防止它在到达方法范围的末尾时被释放。例如,标题或私有界面中的以下内容:
@property (nonatomic, strong) NSTask *activeTask;
然后在方法结束时设置:
self.activeTask = task;