Domanda

Ecco il mio codice:

task = [[NSTask alloc] init];
[task setCurrentDirectoryPath:@"/applications/jarvis/brain/"];
[task setLaunchPath:@"/applications/jarvis/brain/server.sh"];

NSPipe * out = [NSPipe pipe];
[task setStandardOutput:out];

[task launch];
[task waitUntilExit];
[task release];

NSFileHandle * read = [out fileHandleForReading];
NSData * dataRead = [read readDataToEndOfFile];
NSString * stringRead = [[[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding] autorelease];

Così sto cercando di replicare questo:

cd /applications/jarvis/brain/
./server.sh

ma utilizzando NSTask in Objective-C.

Per qualche ragione, però, quando si esegue questo codice, stringRead, non restituisce nulla. Dovrebbe restituire ciò terminale sta tornando quando lancio il file .sh. Corretto?

Tutte le idee?

Elia

È stato utile?

Soluzione

Xcode Bug
C'è un bug in Xcode che impedisce di stampare qualsiasi uscita dopo una viene lanciata una nuova attività utilizzando standard output (che raccoglie tutti gli output, ma non le stampe più nulla). Si sta andando ad avere per chiamata [task setStandardInput:[NSPipe pipe]] per convincerlo per mostrare di nuovo in uscita (o, in alternativa, hanno il compito di stampa stderr invece di stdout).


Suggerimento per il codice finale:

NSTask *server = [NSTask new];
[server setLaunchPath:@"/bin/sh"];
[server setArguments:[NSArray arrayWithObject:@"/path/to/server.sh"]];
[server setCurrentDirectoryPath:@"/path/to/current/directory/"];

NSPipe *outputPipe = [NSPipe pipe];
[server setStandardInput:[NSPipe pipe]];
[server setStandardOutput:outputPipe];

[server launch];
[server waitUntilExit]; // Alternatively, make it asynchronous.
[server release];

NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile];
NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; // Autorelease optional, depending on usage.

Altri suggerimenti

La soluzione di cui sopra è gelida perché è sincrono. Chiama per blocchi [server waitUntilExit] il ciclo di esecuzione fino a quando i compiti è fatto.

Ecco la soluzione asincrona per ottenere l'uscita compito.

task.standardOutput = [NSPipe pipe];
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) {
    NSData *data = [file availableData]; // this will read to EOF, so call only once
    NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);

    // if you're collecting the whole output of a task, you may store it on a property
    [self.taskOutput appendData:data];
}];

Probabilmente si desidera ripetere la stessa sopra per task.standardError.

IMPORTANTE:

Quando il tuo termina compito, è necessario impostare blocco readabilityHandler a zero; in caso contrario, si incontrano elevato utilizzo della CPU, come la lettura non si fermerà mai.

[task setTerminationHandler:^(NSTask *task) {

    // do your stuff on completion

    [task.standardOutput fileHandleForReading].readabilityHandler = nil;
    [task.standardError fileHandleForReading].readabilityHandler = nil;
}];

Questo è tutto asincrono (e si dovrebbe farlo asincrona), in modo che il metodo deve avere una ^ blocco di completamento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top