所以,这是我的代码:
- (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];
}
我尝试使用参数(例如,由php /usr/bin/php
解释的文件)运行命令(例如test.php
处的php解释器)。
事情是:
Data Ready
和Task Terminated
通知之前我已经设法获得所有输出。 (我的意思是,
dataReady:
函数只提取了第一部分
输出,其余部分无处可寻......)我基本上想要异步读取所有输出 - 当命令运行时。
任何想法?我做错了什么?
谢谢!
答案 0 :(得分:4)
您使用readInBackgroundAndNotify
来安排阅读。此方法只读取一个充满数据的缓冲区并通知。您需要再次在通知方法中调用readInBackgroundAndNotify
以阅读更多数据,或者如果您想一次接收所有数据,则需要使用readToEndOfFileInBackgroundAndNotify
。
答案 1 :(得分:1)
自10.7以来有一个新API,因此您可以避免使用NSNotifications。
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];
}];
重要:
当你的任务终止时,你必须将readabilityHandler块设置为nil;否则,您将遇到高CPU使用率,因为读数永远不会停止。
[task setTerminationHandler:^(NSTask *task) {
// do your stuff on completion
[task.standardOutput fileHandleForReading].readabilityHandler = nil;
[task.standardError fileHandleForReading].readabilityHandler = nil;
}];