0

I need to read the output of an NSTask. The code from this post achieves this:How to receive output of NSTask in Cocoa?. However, I want to pass in additional data to this function. I tried to create a dictionary and pass that in through the selector but that didn't work.

NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:completion_, @"a", [outputPipe fileHandleForReading], @"b", nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readCompleted:) name:NSFileHandleReadToEndOfFileCompletionNotification object:dict];

Any ideas?

Community
  • 1
  • 1
Nate
  • 510
  • 1
  • 4
  • 21

2 Answers2

0

First, the object: parameter of -addObserver:selector:name:object: is the thing which will be posting the notification. If a notification of the specified name is posted by a different object, the notification center does not invoke your selector. Since your dictionary will never be posting NSFileHandleReadToEndOfFileCompletionNotification (because dictionaries don't post notifications), your selector will never be invoked.

So, don't pass a dictionary as the object. It doesn't do what you think. It's not a means of passing information in to the observing method.

You can use the more modern, block-based observer method to do this:

__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;
                                                                       }];

You have to be careful to keep the observation object alive until the notification fires but also remove it and release it (by clearing the strong reference) once it does. I've shown that above.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
0

Here's the async solution for getting the task output.

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];

}];

Kakashi
  • 31
  • 6