-1
我是新來的目標c。我正在使用以下代碼在目標c中執行命令行API。代碼對我來說工作正常。但爲什麼這段代碼使用NSRunLoop?命令行API和waitForDataInBackgroundAndNotify
-(void)uploadData
{
setenv([@"PASSWORD" UTF8String], [mPassword UTF8String], 1);
[task setLaunchPath:executablePathRoot];
[task setArguments:array];
NSPipe *pipe = [NSPipe pipe];
NSPipe *errorPipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task setStandardError:errorPipe];
//keeps your log where it belongs
//[task setStandardInput:[NSPipe pipe]];
NSFileHandle *outFile = [pipe fileHandleForReading];
NSFileHandle *errFile = [errorPipe fileHandleForReading];
[task launch];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(terminated:)
name:NSTaskDidTerminateNotification
object:task];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(outData:)
name:NSFileHandleDataAvailableNotification
object:outFile];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(errData:)
name:NSFileHandleDataAvailableNotification
object:errFile];
[outFile waitForDataInBackgroundAndNotify];
[errFile waitForDataInBackgroundAndNotify];
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
while(!terminated)
{
if (![[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
{
break;
}
[pool release];
pool = [[NSAutoreleasePool alloc] init];
}
[pool release];
[self appendDataFrom:outFile to:output];
[self appendDataFrom:errFile to:error];
//[task waitUntilExit];
[task release];
}
-(void) outData: (NSNotification *) notification
{
NSLog(@"outData");
NSFileHandle *fileHandle = (NSFileHandle*) [notification object];
[self appendDataFrom:fileHandle to:output];
[fileHandle waitForDataInBackgroundAndNotify]; //Checks to see if data is available in a background thread.
}
-(void) errData: (NSNotification *) notification
{
NSLog(@"errData");
NSFileHandle *fileHandle = (NSFileHandle*) [notification object];
[self appendDataFrom:fileHandle to:output];
[fileHandle waitForDataInBackgroundAndNotify];
}
- (void) terminated: (NSNotification *)notification
{
NSLog(@"Task terminated");
[[NSNotificationCenter defaultCenter] removeObserver:self];
terminated =YES;
}
我不同意你對運行循環代碼的修改。你應該總是在運行循環周圍使用自動釋放池,因爲你永遠不知道在迭代中將創建多少數據並自動釋放。如果'runMode:beforeDate:'返回'NO',因爲它指示了一個錯誤(或者沒有輸入源,這是一個錯誤,因爲管道應該連接到它),所以中斷循環也是適當的。 – ughoavgfhw
@ughoavgfhw我同意如果我們知道我們要優化什麼,那麼可以在那裏使用自動釋放池。但是,我認爲,我們不應該總是把它用作預防手段,因爲我們不知道會創建多少數據。我們已經在當前線程中有一個autorelease池,它會完成這項工作。 – Davyd
@ughoavgfhw我同意,應該處理runMode:beforeDate的負面結果。 – Davyd