2010-05-16 7 views
2

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

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; 
} 
+1

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. –

+0

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]; –