Jus*_*ams 3 macos cocoa nstask
我有一些代码可以处理从我的应用程序导出数据.它接收一个充满XML的NSString,并通过PHP脚本运行它来生成HTMl,RTF等.除非用户有一个大的列表,否则它运行良好.这显然是因为它超过了8k左右的NSPipe缓冲区.
我在readPipe和readHandle中解决了这个问题(我认为),但我不确定如何在writeHandle/writePipe中处理它.[writeHandle writeData:[in...除非我在gdb中打破它,等待几秒然后继续,否则应用程序将会出现问题.
有关如何在我的代码中解决此问题的任何帮助?
- (NSString *)outputFromExporter:(COExporter *)exporter input:(NSString *)input {
NSString *exportedString = nil;
NSString *path = [exporter path];
NSTask *task = [[NSTask alloc] init];
NSPipe *writePipe = [NSPipe pipe];
NSFileHandle *writeHandle = [writePipe fileHandleForWriting];
NSPipe *readPipe = [NSPipe pipe];
NSFileHandle *readHandle = [readPipe fileHandleForReading];
NSMutableData *outputData = [[NSMutableData alloc] init];
NSData *readData = nil;
// Set the launch path and I/O for the task
[task setLaunchPath:path];
[task setStandardInput:writePipe];
[task setStandardOutput:readPipe];
// Launch the exporter, it will convert the raw OPML into HTML, Plaintext, etc
[task launch];
// Write the raw OPML representation to the exporter's input stream
[writeHandle writeData:[input dataUsingEncoding:NSUTF8StringEncoding]];
[writeHandle closeFile];
while ((readData = [readHandle availableData]) && [readData length]) {
[outputData appendData:readData];
}
exportedString = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
return exportedString;
}
Run Code Online (Sandbox Code Playgroud)
sup*_*rin 11
自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];
}];
Run Code Online (Sandbox Code Playgroud)
可能你想重复上面的相同task.standardError.
重要:
当您的任务终止时,您必须将readabilityHandler块设置为nil; 否则,您将遇到高CPU使用率,因为读数永远不会停止.
[task setTerminationHandler:^(NSTask *task) {
// do your stuff on completion
[task.standardOutput fileHandleForReading].readabilityHandler = nil;
[task.standardError fileHandleForReading].readabilityHandler = nil;
}];
Run Code Online (Sandbox Code Playgroud)
这都是异步的(你应该做异步),所以你的方法应该有一个^完成块.