我寫了一個NSTask
異步執行方法爲簡單的python腳本。無法從NSTask的stdout獲得中間輸出?
然後python腳本只是打印到標準輸出,一切都很好。 當那裏有一個raw_input
(期待來自用戶的輸入)時,它肯定會得到正確的輸入,但它不能打印數據之前raw_input
。
發生了什麼事?
- (NSString*)exec:(NSArray *)args environment:(NSDictionary*)env action:(void (^)(NSString*))action completed:(void (^)(NSString*))completed
{
_task = [NSTask new];
_output = [NSPipe new];
_error = [NSPipe new];
_input = [NSPipe new];
NSFileHandle* outputF = [_output fileHandleForReading];
NSFileHandle* errorF = [_error fileHandleForReading];
NSFileHandle* inputF = [_input fileHandleForWriting];
__block NSString* fullOutput = @"";
NSMutableDictionary* envs = [NSMutableDictionary dictionary];
NSArray* newArgs = @[@"bash",@"-c"];
[_task setLaunchPath:@"/usr/bin/env"];
if (env)
for (NSString* key in env)
envs[key] = env[key];
if ([envs count]) [_task setEnvironment:envs];
NSString* cmd = @"";
cmd = [cmd stringByAppendingString:[[[self sanitizedArgs:args] componentsJoinedByString:@" "] stringByAppendingString:@" && echo \":::::$PWD:::::\""]];
[_task setArguments:[newArgs arrayByAddingObject:cmd]];
[_task setStandardOutput:_output];
[_task setStandardError:_error];
[_task setStandardInput:_input];
void (^outputter)(NSFileHandle*) = ^(NSFileHandle *file){
NSData *data = [file availableData];
NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Output: %@",str);
action(str);
fullOutput = [fullOutput stringByAppendingString:str];
};
void (^inputter)(NSFileHandle*) = ^(NSFileHandle *file) {
NSLog(@"In inputter");
NSData *data = [[_task.standardOutput fileHandleForReading] availableData];
NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Output: %@",str);
};
[outputF setReadabilityHandler:outputter];
[errorF setReadabilityHandler:outputter];
//[inputF setWriteabilityHandler:inputter];
[_task setTerminationHandler:^(NSTask* task){
NSLog(@"Terminated: %@",fullOutput);
completed(fullOutput);
//[task.standardOutput fileHandleForReading].readabilityHandler = nil;
//[task.standardError fileHandleForReading].readabilityHandler = nil;
//[task.standardInput fileHandleForWriting].writeabilityHandler = nil;
//[task terminate];
//task = nil;
}];
[_task launch];
//[[_input fileHandleForWriting] waitForDataInBackgroundAndNotify];
return @"";
}
附:我到處尋找解決方案,但似乎沒有發現任何東西。它看起來像有很多NSTask
演練和教程,但 - 有趣的巧合 - 他們通常避免處理任何stdin
影響