【问题标题】:Get Notification of task progress from NSTask从 NSTask 获取任务进度通知
【发布时间】:2013-07-22 12:59:21
【问题描述】:

任何人都知道在执行 NSTask 时从 NSTask 获取通知。我正在使用 NSTask 解压缩一个 zip 文件,并且需要在 NSProgressBar 中显示解压缩数据的进度。 我没有找到执行此类任务的任何想法。所以我在进度栏中显示值。 需要帮助来完成这项任务。 提前致谢。

【问题讨论】:

    标签: macos cocoa nstask nsnotification


    【解决方案1】:

    使用NSFileHandleReadCompletionNotificationNSTaskDidTerminateNotification 通知。

    task=[[NSTask alloc] init];
    
    [task setLaunchPath:Path];
    
    NSPipe *outputpipe=[[NSPipe alloc]init];
    
    NSPipe *errorpipe=[[NSPipe alloc]init];
    
    NSFileHandle *output,*error;
    
    [task setArguments: arguments];
    
    [task setStandardOutput:outputpipe];
    
    [task setStandardError:errorpipe];
    
    output=[outputpipe fileHandleForReading];
    
    error=[errorpipe  fileHandleForReading];
    
    [task launch]; 
    
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedData:)  name: NSFileHandleReadCompletionNotification object:output];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedError:)  name: NSFileHandleReadCompletionNotification object:error];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TaskCompletion:)  name: NSTaskDidTerminateNotification object:task];
    
    //[input writeData:[NSMutableData initWithString:@"test"]];
    [output readInBackgroundAndNotify];
    
    [error readInBackgroundAndNotify];
    
    
    [task waitUntilExit];
    
    [outputpipe release];
    
    [errorpipe release];
    [task release];
    [pool release];
    
    
    /* Called when there is some data in the output pipe */
    
    -(void) receivedData:(NSNotification*) rec_not
    
    {
    
        NSData *dataOutput=[[rec_not userInfo] objectForKey:NSFileHandleNotificationDataItem];
    
        [[rec_not object] readInBackgroundAndNotify];
    
        [strfromdata release];
    
    }
    
    /* Called when there is some data in the error pipe */
    
    -(void) receivedError:(NSNotification*) rec_not
    
    {
        NSData *dataOutput=[[rec_not userInfo] objectForKey:NSFileHandleNotificationDataItem];
    
        if( !dataOutput)
    
            NSLog(@">>>>>>>>>>>>>>Empty Data");
    
        [[rec_not object] readInBackgroundAndNotify];
    
    
    }
    
    /* Called when the task is complete */
    
    -(void) TaskCompletion :(NSNotification*) rec_not
    
    {   
    
    }
    

    【讨论】:

    • 这些可以告诉您解压缩何时结束,但不会告诉您解压缩的距离。
    • 彼得是对的,这些通知在流程完成时调用,而不是在流程执行时调用。
    【解决方案2】:

    为了显示进度,您需要找出两件事:

    • 存档中有多少文件,或者解压缩完成后它们将占用多少字节
    • 到目前为止,您解压了多少文件或字节数

    您可以通过阅读解压缩任务的输出找到这些信息。 Parag Bafna 的回答是一个开始;在receivedData: 中,您需要解析输出以确定刚刚发生的进度,然后将该进度添加到到目前为止的运行进度计数中(例如,++_filesUnzippedSoFar)。

    第一部分,找出工作的总规模,比较棘手。你基本上需要在运行解压缩之前运行解压缩:第一个,-l(这是一个小写的 L),是列出存档的内容;二是解压。第一个,您读取输出以确定存档包含多少文件/字节;第二个,您读取输出以确定进度条前进到的值。

    设置进度条的属性很简单;这些实际上只是doubleValuemaxValue。弄清楚你在工作中的位置是困难的部分,并且是非常特定于领域的——你需要阅读 unzip 的输出(两次,以不同的形式),理解它告诉你的内容,并将其转化为进度信息。

    在 NSTask 中没有任何东西可以帮助你。 NSTask 的这一部分从standardOutput 属性开始和结束。它不知道 zip 文件、档案、档案内容甚至进度,因为这些都不适用于大多数任务。这一切都特定于你的任务,这意味着必须编写代码来完成它。

    【讨论】:

    • 第二个是问题。我们怎么能得到,到目前为止你解压了多少文件或字节,因为 NSTask 方法 waitUntilExit 在完成任务后返回我们命令。
    • @Student:就像我说的,这不是 NSTask 的工作——需要读取和解析 unzip 的输出。
    • 我可以解析解压缩的输出,但是你能解释一下在执行过程中如何从 NSTask 获取输出吗?
    • @Student:将任务的 standardOutput 设置为 NSPipe,然后从管道的 fileHandleForReading 中读取。最好的读取方法是将文件句柄的readabilityHandler 设置为处理该输出块的块。另一种方法是 Parag Bafna 展示的:为 NSFileHandleReadCompletionNotification 添加一个观察者到本地通知中心,将文件句柄作为通知对象,并重复调用 readInBackgroundAndNotify——但这与基于块的 API 相比非常尴尬。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 2015-09-27
    • 2019-03-04
    • 1970-01-01
    相关资源
    最近更新 更多