Existe-t-il un moyen de lancer un script shell et d'afficher la sortie dans un NSTextView? Je ne veux pas du tout d'entrée de l'utilisateur dans le script shell, puisqu'il est juste appelé pour compiler un buch de fichiers. La partie script shell fonctionne très bien jusqu'à présent, mais je n'arrive pas à comprendre comment l'exécuter et afficher la sortie dans un NSTextView. Je sais qu'un script shell peut être exécuté en utilisant system() et NSTask, mais comment puis-je obtenir sa sortie dans un NSTextView?Obtenir la sortie d'un script shell dans Cocoa
2
A
Répondre
3
Si vous voulez extension générique puis passer votre commande unix/bin/sh
- (NSString *)unixSinglePathCommandWithReturn:(NSString *) command {
// performs a unix command by sending it to /bin/sh and returns stdout.
// trims trailing carriage return
// not as efficient as running command directly, but provides wildcard expansion
NSPipe *newPipe = [NSPipe pipe];
NSFileHandle *readHandle = [newPipe fileHandleForReading];
NSData *inData = nil;
NSString* returnValue = nil;
NSTask * unixTask = [[NSTask alloc] init];
[unixTask setStandardOutput:newPipe];
[unixTask setLaunchPath:@"/bin/csh"];
[unixTask setArguments:[NSArray arrayWithObjects:@"-c", command , nil]];
[unixTask launch];
[unixTask waitUntilExit];
int status = [unixTask terminationStatus];
while ((inData = [readHandle availableData]) && [inData length]) {
returnValue= [[NSString alloc]
initWithData:inData encoding:[NSString defaultCStringEncoding]];
returnValue = [returnValue substringToIndex:[returnValue length]-1];
NSLog(@"%@",returnValue);
}
return returnValue;
}
1
NSTask
possède la méthode setStandardOutput
qui accepte l'objet NSFileHandle
ou NSPipe
. Donc, si vous créez objet NSPipe
et définissez comme NSTask
« s standardOutput
vous pouvez ensuite utiliser NSPipe
» s fileHandleForReading
pour obtenir NSFileHandle
à partir de laquelle, à son tour, vous serez en mesure de readDataToEndOfFile
ou readDataOfLength:
vous voulez. Donc, quelque chose comme cela ferait (code non testé):
- (void)setupTask {
// assume it's an ivar
standardOutputPipe = [[NSPipe alloc] init];
[myTask setStandardOutput:standardOutputPipe];
// other setup code goes below
}
// reading data to NSTextField
- (void)updateOutputField {
NSFileHandle *readingFileHandle = [standardOutputPipe fileHandleForReading];
NSData *newData;
while ((newData = [readingFileHandle availableData])) {
NSString *newString = [[[NSString alloc] initWithData:newData encoding: NSASCIIStringEncoding] autorelease];
NSString *wholeString = [[myTextField stringValue] stringByAppendingString:newString];
[myTextField setStringValue:wholeString];
}
[standardOutputPipe release];
standardOutputPipe = nil;
}
En fonction de la durée de la tâche sera exécutée, il peut mieux vaut lire les données en arrière-plan, en utilisant l'une des méthodes de NSFileHandle pour cela. –
Je suis fondamentalement faire ce que vous dites ci-dessus, et en exécutant le champ de sortie de mise à jour en arrière-plan en utilisant un thread, la tâche s'exécute, mais je ne vois jamais rien dans le textview. Il est correctement câblé. Voici le code pour l'exécution en arrière-plan: '[NSThread detachNewThreadSelector: @selector (updateOutputField :) toTarget: self avecObject: nil];' Affiche la sortie dans le débogueur, mais dans le champ de texte. Le lancer est comme ceci: [myTask setLaunchPath: @ "/ bin/sh"]; [myTask setArguments: [NSArray arrayWithObjects: scr], néant]]; \t [myTask setStandardOutput: standardOutputPipe]; [lancement de myTask]; –