NSTask终止处理程序仅在我发送waitUntilExit时运行

时间:2013-10-03 18:09:43

标签: objective-c macos cocoa nstask

我有一个类遍历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并运行命令吧。

3 个答案:

答案 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;