2

だから、これは私のコードです:

- (void)runCmd:(NSString *)cmd withArgs:(NSArray *)args
{
    NSLog(@"\nRunning ::\n\tCmd : %@\n\tArgs : %@",cmd, args);
    [theSpinner start];
    if (task)
    {
        [task interrupt];

    }
    else
    {
        task = [[NSTask alloc] init];
        [task setLaunchPath:cmd];

        [task setArguments:args];

        [pipe release];

        pipe = [[NSPipe alloc] init];
        [task setStandardOutput:pipe];

        NSFileHandle* fh = [pipe fileHandleForReading];

        NSNotificationCenter* nc;

        nc = [NSNotificationCenter defaultCenter];
        [nc removeObserver:self];
        [nc addObserver:self 
               selector:@selector(dataReady:) 
                   name:NSFileHandleReadCompletionNotification 
                 object:fh];
        [nc addObserver:self selector:@selector(dataAvailable:) name:NSFileHandleDataAvailableNotification object:fh];
        [nc addObserver:self 
               selector:@selector(taskTerminated:) 
                   name:NSTaskDidTerminateNotification 
                 object:task];

        [task launch];
        [fh readInBackgroundAndNotify];
    }
}

- (void)dataAvailable:(NSNotification*)n
{
    NSLog(@"Data Available : %@",n);
}

- (void)dataReady:(NSNotification*)n
{
    NSData* d;

    d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem];

    NSLog(@"Data Ready : %@",n);

    if ([d length])
    {
        NSLog(@"Data Ready : %@",[[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding]);
    }
}

- (void) taskTerminated:(NSNotification*)note
{
    NSLog(@"Task Terminated : %@",note);
    [task release];
    task = nil;
    [theSpinner stop];

    NSAlert *alert = [[[NSAlert alloc] init] autorelease];
    [alert setMessageText:[NSString stringWithFormat:@"Command finished"]];

    [alert runModal];
}

/usr/bin/php引数(たとえば、phpによって解釈されるファイル)を使用してコマンド(たとえば、phpインタープリター)を実行してみましたtest.php

事は:

  • スクリプトは正常に実行されます
  • Data Readyしかし、すべての出力を取得する前に、Task Terminated 通知を受信して​​います。(つまり、dataReady:関数は出力の最初の部分だけをフェッチし
    、残りはどこにも見つかりません...)

基本的に、コマンドの実行中に、すべての出力を非同期で読み取りたいと思います。

何か案は?私は何が間違っているのですか?

ありがとう!

4

2 に答える 2

4

readInBackgroundAndNotifyあなたはあなたの読書をスケジュールするために使用します。このメソッドは、データでいっぱいの1つのバッファーのみを読み取り、通知します。readInBackgroundAndNotifyさらにデータを読み取るには、通知メソッドを再度呼び出す必要があります。またはreadToEndOfFileInBackgroundAndNotify、すべてのデータを一度に受信する場合は、を使用する必要があります。

于 2012-04-01T15:08:34.180 に答える
1

10.7以降に新しいAPIがあるため、NSNotificationsの使用を回避できます。

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

重要:

タスクが終了したら、readabilityHandlerブロックをnilに設定する必要があります。そうしないと、読み取りが停止しないため、CPU使用率が高くなります。

[task setTerminationHandler:^(NSTask *task) {

    // do your stuff on completion

    [task.standardOutput fileHandleForReading].readabilityHandler = nil;
    [task.standardError fileHandleForReading].readabilityHandler = nil;
}];
于 2013-04-29T08:44:45.133 に答える