0

私は Objective-C を初めて使用するので、何かが足りない場合はご容赦ください。しかし、私たちはどこかから始めなければなりません:)

コマンドを実行し、結果を別のメソッドに渡す別のオープン ソース プロジェクトから取得したコード スニペットがあります。私がする必要があるのは、標準出力に出力される新しい行ごとにリッスンし、各行で何かを行うことです。

私が取り組んでいるコードスニペットは次のとおりです。

    NSMutableArray *args  = [NSMutableArray array];

    NSString *input = [details valueForKey:@"input"];

    for (NSString *i in [input componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]) {
        [args addObject:i];
    }

    NSTask *scriptTask = [NSTask new];
    NSPipe *outputPipe = [NSPipe pipe];

    if ([_NSFileManager() isExecutableFileAtPath:scriptPath] == NO) {
        NSArray *chmodArguments = @[@"+x", scriptPath];

        NSTask *chmod = [NSTask launchedTaskWithLaunchPath:@"/bin/chmod" arguments:chmodArguments];

        [chmod waitUntilExit];
    }

    [scriptTask setStandardOutput:outputPipe];
    [scriptTask setLaunchPath:scriptPath];
    [scriptTask setArguments:args];

    NSFileHandle *filehandle = [outputPipe fileHandleForReading];

    [scriptTask launch];
    [scriptTask waitUntilExit];

    NSData *outputData = [filehandle readDataToEndOfFile];

    NSString *outputString  = [NSString stringWithData:outputData encoding:NSUTF8StringEncoding];

    if (NSObjectIsNotEmpty(outputString)) {
        [self.world.iomt inputText:outputString command:IRCPrivateCommandIndex("privmsg")];
    }

したがって、プロセスが完了するのを待ってから結果を処理するのではなく、コマンドによって標準出力に出力される新しい行ごとに待機する必要があります。

私のバックグラウンドは主に Web 開発者なので、Node.js とイベント エミッターを使用している場合、私の目的は次のようになると思います。

task = new Task("ls");

task.addListener("newline", function(data) {
    somethingElse("sendmsg", data);
});

task.run();

私が達成しようとしていることを理解していただければ幸いです。ありがとう!

4

1 に答える 1

0

できることは、オブザーバーを NSFileHandle に追加して、何かを読み取ったときに通知することです。

例:

[fileHandler readInBackgroundAndNotify];
//Need to set NSTask output pipes
[self.task setStandardOutput: outputPipe];
[self.task setStandardError: outputPipe];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readFromTask:) name:NSFileHandleReadCompletionNotification object:fileHandler];

-(void)readFromTask:(NSNotification *)aNotifcation;
    {
        NSData *data = [[aNotifcation userInfo] objectForKey: NSFileHandleNotificationDataItem];
        if (data != 0) {
            NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

                // Do something with the text

            [text release];
            [[aNotifcation object] readInBackgroundAndNotify];  
        }
    }

次に、タスクが完了したことを示すためにタスクに追加できる通知があり、クリーンアップを行うことができます。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskEnded:) name:NSTaskDidTerminateNotification object:task];



- (void)taskEnded:(NSNotification *) aNotifcation
{
    NSData *data = [[aNotifcation userInfo] objectForKey: NSFileHandleNotificationDataItem];
    if (data != 0) {
        NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    [text release];

}

[self.task release];

}

したがって、コードから次のものを削除できます。

 [scriptTask waitUntilExit];

そして、データ処理を通知に移動します。

NSData *outputData = [filehandle readDataToEndOfFile];

NSString *outputString  = [NSString stringWithData:outputData encoding:NSUTF8StringEncoding];

if (NSObjectIsNotEmpty(outputString)) {
    [self.world.iomt inputText:outputString command:IRCPrivateCommandIndex("privmsg")];
}

それは大まかなアイデアです。良い投稿があります

http://www.cocoabuilder.com/archive/cocoa/306145-nstask-oddity-with-getting-stdout.html

于 2012-10-27T12:39:30.783 に答える