【问题标题】:Passing extra data to NSTask output handler将额外数据传递给 NSTask 输出处理程序
【发布时间】:2015-02-18 20:51:19
【问题描述】:
我需要读取 NSTask 的输出。这篇文章中的代码实现了这一点:How to receive output of NSTask in Cocoa?。但是,我想向这个函数传递额外的数据。我试图创建一个字典并通过选择器将其传递,但这没有用。
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:completion_, @"a", [outputPipe fileHandleForReading], @"b", nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readCompleted:) name:NSFileHandleReadToEndOfFileCompletionNotification object:dict];
有什么想法吗?
【问题讨论】:
标签:
macos
nsnotificationcenter
nstask
nsnotification
【解决方案1】:
首先,-addObserver:selector:name:object: 的 object: 参数是发布通知的对象。如果指定名称的通知由不同的对象发布,通知中心不会调用您的选择器。由于您的字典永远不会发布NSFileHandleReadToEndOfFileCompletionNotification(因为字典不会发布通知),因此您的选择器将永远不会被调用。
所以,不要将字典作为object 传递。它不会像你想的那样做。这不是将信息传递给观察方法的方法。
您可以使用更现代的基于块的观察者方法来执行此操作:
__block id observation = [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleReadToEndOfFileCompletionNotification
object:[outputPipe fileHandleForReading]
queue:nil
usingBlock:^(NSNotification *note) {
// Do whatever you want to do in response to the notification here.
// You can access the completion_ variable directly.
[[NSNotificationCenter defaultCenter] removeObserver:observation];
observation = nil;
}];
在通知触发之前,您必须小心保持观察对象处于活动状态,但一旦触发就将其移除并释放(通过清除强引用)。我已经在上面展示了。
【解决方案2】:
这是获取任务输出的异步解决方案。
task.standardOutput = [NSPipe pipe];
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) {
NSData *data = [file availableData]; // this will read to EOF, so call only once
NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// if you're collecting the whole output of a task, you may store it on a property
//[self.taskOutput appendData:data];
}];