Je suis nouveau à l'objectif c. J'utilise le code suivant pour exécuter l'API de ligne de commande dans l'objectif c. le code fonctionne bien pour moi. mais pourquoi ce code utilise NSRunLoop?API de ligne de commande et 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;
}
Je ne suis pas d'accord sur vos modifications du code de la boucle d'exécution. Vous devriez toujours utiliser un pool autorelease autour d'une boucle d'exécution, puisque vous ne savez jamais combien de données seront créées et auto libérées dans une itération. Il est également approprié de rompre la boucle si 'runMode: beforeDate:' renvoie 'NO', car cela indique une erreur (ou aucune source d'entrée, ce qui est une erreur puisque les tuyaux doivent être connectés). – ughoavgfhw
@ughoavgfhw Je suis d'accord qu'un pool autorelease peut être utilisé si nous savons ce que nous allons optimiser. Cependant, je suis certain que nous ne devrions pas toujours l'utiliser comme moyen préventif simplement parce que nous ne savons pas combien de données seront créées. Nous avons déjà un pool d'autorelease dans le thread actuel, il fera l'affaire. – Davyd
@ughoavgfhw Je suis d'accord, le résultat négatif de runMode: beforeDate: devrait être géré. – Davyd