2011-09-28 2 views
-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; 
} 

답변

4

이것은 uploadData 데이터를 동기화하는 것입니다. terminated 플래그가 YES로 설정 될 때까지 실행은 while 루프를 종료 할 수 없습니다. 다음 전화

[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] 

을 사용하면 앱이 다른 이벤트를 처리 할 수 ​​있습니다. 따라서 NSTaskDidTerminateNotification이 수신되면 종료 플래그가 변경되고 while 루프가 완료됩니다.

그러나 여기서 자동 복구 풀을 할당 할 필요는 없습니다. 또한 코드가 과도합니다. 그것은 훨씬 더 간단 할 수 있습니다

while(!terminated) 
{ 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
} 

업데이트 : beforeDate : 조건에 계정 ughoavgfhw의 의견을 고려의가 RunMode에의 결과를 포함하여 전화도 안전 할 수 있습니다.

while(!terminated && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); 
+1

실행 루프 코드를 수정 한 것에 동의하지 않습니다. 반복 루프에서 자동으로 생성되고 자동 릴리즈되는 데이터의 양을 모르기 때문에 항상 실행 루프 주위에 자동 복구 풀을 사용해야합니다. 'runMode : beforeDate :'가'NO'를 리턴하면 에러를 나타 내기 때문에 (또는 파이프가 연결되어야하기 때문에 오류 인 입력 소스가 없기 때문에) 루프를 깨는 것이 적절합니다. – ughoavgfhw

+0

@ughoavgfhw 우리가 최적화하려고하는 것을 안다면 autorelease 풀을 사용할 수 있다는 데 동의합니다. 그러나 나는 데이터가 얼마나 생성 될지 모르기 때문에 항상 예방 수단으로 사용하지 않아야한다고 확신합니다. 우리는 이미 현재 쓰레드에 autorelease pool을 가지고있다. – Davyd

+0

@ughoavgfhw 동의합니다. runMode : beforeDate :가 부정적인 결과를 처리해야합니다. – Davyd