So, this is my code :
- (void)runCmd:(NSString *)cmd withArgs:(NSArray *)args
{
NSLog(@"\nRunning ::\n\tCmd : %@\n\tArgs : %@",cmd, args);
[theSpinner start];
if (task)
{
[task interrupt];
}
else
{
task = [[NSTask alloc] init];
[task setLaunchPath:cmd];
[task setArguments:args];
[pipe release];
pipe = [[NSPipe alloc] init];
[task setStandardOutput:pipe];
NSFileHandle* fh = [pipe fileHandleForReading];
NSNotificationCenter* nc;
nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self];
[nc addObserver:self
selector:@selector(dataReady:)
name:NSFileHandleReadCompletionNotification
object:fh];
[nc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleDataAvailableNotification object:fh];
[nc addObserver:self
selector:@selector(taskTerminated:)
name:NSTaskDidTerminateNotification
object:task];
[task launch];
[fh readInBackgroundAndNotify];
}
}
- (void)dataAvailable:(NSNotification*)n
{
NSLog(@"Data Available : %@",n);
}
- (void)dataReady:(NSNotification*)n
{
NSData* d;
d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem];
NSLog(@"Data Ready : %@",n);
if ([d length])
{
NSLog(@"Data Ready : %@",[[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding]);
}
}
- (void) taskTerminated:(NSNotification*)note
{
NSLog(@"Task Terminated : %@",note);
[task release];
task = nil;
[theSpinner stop];
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:[NSString stringWithFormat:@"Command finished"]];
[alert runModal];
}
I’ve tried running a command (e.g. the php interpreter at /usr/bin/php) with arguments (e.g. the file to be interpreted by php test.php).
The thing is :
- The script runs fine
- BUT, I’m receiving a
Data ReadyandTask Terminated
notification BEFORE I’ve managed to get all the output. (I mean,
thedataReady:function fetches just the first part of the
output and the rest of it is nowhere to be found…)
I basically want to be reading, asynchronously, all output – WHILE the command is running.
Any Ideas? What am I doing wrong?
Thanks!
You use
readInBackgroundAndNotifyto schedule your reading. This method reads only one buffer full of data and notifies. You either need to callreadInBackgroundAndNotifyin your notification method again to read more data or you need to usereadToEndOfFileInBackgroundAndNotifyif you want to receive all the data at once.