开发者

Command Line API and waitForDataInBackgroundAndNotify

开发者 https://www.devze.com 2023-04-09 02:55 出处:网络
I am new to objective c.i am using following code to execute command line API in objective c. code is working fine for me. but why this code is using NSRunLoop?

I am new to objective c. i am using following code to execute command line API in objective c. code is working fine for me. but why this code is using NSRunLoop?

-(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 *) notifica开发者_如何学Pythontion
{
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;
}


This is to make the method uploadData synchronous. The execution cannot quit the while loop until the terminated flag is set YES. The following call

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

allows the app to process other events. So, when the NSTaskDidTerminateNotification received the terminated flag will be changed and the while loop finishes.

However, there is no need to allocate an autorelease pool here. Also, the code is excessive. It can much simpler:

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

Update: Taking into account ughoavgfhw's comments, let's make the call even safer by including the result of runMode: beforeDate: into the condition.

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

精彩评论

暂无评论...
验证码 换一张
取 消