【问题标题】:Getting process output using NSTask on-the-go?随时随地使用 NSTask 获取流程输出?
【发布时间】:2014-05-29 16:02:06
【问题描述】:

我想得到NSTask 的输出,因为它似乎不等到进程完成。 我找到了this answer,但是应该如何修改它以尽快获取数据?我想我应该以某种方式运行后台线程并一直等待输出。

【问题讨论】:

    标签: objective-c nstask


    【解决方案1】:

    您可以注册NSFileHandleDataAvailableNotification 通知以阅读 从任务输出异步。示例:

    NSTask *task = [[NSTask alloc] init];
    [task setLaunchPath:@"/bin/ls"];
    [task setCurrentDirectoryPath:@"/"];
    
    NSPipe *stdoutPipe = [NSPipe pipe];
    [task setStandardOutput:stdoutPipe];
    
    NSFileHandle *stdoutHandle = [stdoutPipe fileHandleForReading];
    [stdoutHandle waitForDataInBackgroundAndNotify];
    id observer = [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
                                                                    object:stdoutHandle queue:nil
                                                                usingBlock:^(NSNotification *note) 
    {
        // This block is called when output from the task is available.
    
        NSData *dataRead = [stdoutHandle availableData];
        NSString *stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
        NSLog(@"output: %@", stringRead);
    
        [stdoutHandle waitForDataInBackgroundAndNotify];
    }];
    
    [task launch];
    [task waitUntilExit];
    [[NSNotificationCenter defaultCenter] removeObserver:observer];
    

    或者,您可以在后台线程上阅读,例如使用 GCD:

    NSTask *task = [[NSTask alloc] init];
    [task setLaunchPath:@"/bin/ls"];
    [task setCurrentDirectoryPath:@"/"];
    
    NSPipe *stdoutPipe = [NSPipe pipe];
    [task setStandardOutput:stdoutPipe];
    
    NSFileHandle *stdoutHandle = [stdoutPipe fileHandleForReading];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        NSData *dataRead = [stdoutHandle availableData];
        while ([dataRead length] > 0) {
            NSString *stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
            NSLog(@"output: %@", stringRead);
            dataRead = [stdoutHandle availableData];
        }
    });
    
    [task launch];
    [task waitUntilExit];
    

    【讨论】:

    • 感谢您的出色回答!顺便提一句。什么是首选方法,为什么?
    • 使用第一个(基于通知的)方法,在主线程上调用该块,如果您执行任何 UI 更新或仅在主线程上允许的其他事情,这可能是相关的。否则我不知道一种方法比另一种方法的优势。
    • 我偶尔会遇到第二个版本的异常:“NSConcreteFileHandle availableData]:资源暂时不可用”
    猜你喜欢
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2012-06-03
    • 1970-01-01
    相关资源
    最近更新 更多