Reputation: 20410
I'd like to get NSTask
output as soon as it appears not waiting until process finishes.
I've found this answer but how it should be modified to get data ASAP? I think i should run background thread and wait for output all the time somehow.
Upvotes: 1
Views: 1348
Reputation: 539685
You can register for the NSFileHandleDataAvailableNotification
notification to read
asynchronously from the task output. Example:
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/ls"];
[task setCurrentDirectoryPath:@"/"];
NSPipe *stdoutPipe = [NSPipe pipe];
[task setStandardOutput:stdoutPipe];
NSFileHandle *stdoutHandle = [stdoutPipe fileHandleForReading];
[stdoutHandle waitForDataInBackgroundAndNotify];
id observer = [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:stdoutHandle queue:nil
usingBlock:^(NSNotification *note)
{
// This block is called when output from the task is available.
NSData *dataRead = [stdoutHandle availableData];
NSString *stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
NSLog(@"output: %@", stringRead);
[stdoutHandle waitForDataInBackgroundAndNotify];
}];
[task launch];
[task waitUntilExit];
[[NSNotificationCenter defaultCenter] removeObserver:observer];
Alternatively, you can read on a background thread, for example with GCD:
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/ls"];
[task setCurrentDirectoryPath:@"/"];
NSPipe *stdoutPipe = [NSPipe pipe];
[task setStandardOutput:stdoutPipe];
NSFileHandle *stdoutHandle = [stdoutPipe fileHandleForReading];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSData *dataRead = [stdoutHandle availableData];
while ([dataRead length] > 0) {
NSString *stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
NSLog(@"output: %@", stringRead);
dataRead = [stdoutHandle availableData];
}
});
[task launch];
[task waitUntilExit];
Upvotes: 4