【发布时间】:2013-07-22 12:59:21
【问题描述】:
任何人都知道在执行 NSTask 时从 NSTask 获取通知。我正在使用 NSTask 解压缩一个 zip 文件,并且需要在 NSProgressBar 中显示解压缩数据的进度。 我没有找到执行此类任务的任何想法。所以我在进度栏中显示值。 需要帮助来完成这项任务。 提前致谢。
【问题讨论】:
标签: macos cocoa nstask nsnotification
任何人都知道在执行 NSTask 时从 NSTask 获取通知。我正在使用 NSTask 解压缩一个 zip 文件,并且需要在 NSProgressBar 中显示解压缩数据的进度。 我没有找到执行此类任务的任何想法。所以我在进度栏中显示值。 需要帮助来完成这项任务。 提前致谢。
【问题讨论】:
标签: macos cocoa nstask nsnotification
使用NSFileHandleReadCompletionNotification、NSTaskDidTerminateNotification 通知。
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
{
}
【讨论】:
为了显示进度,您需要找出两件事:
您可以通过阅读解压缩任务的输出找到这些信息。 Parag Bafna 的回答是一个开始;在receivedData: 中,您需要解析输出以确定刚刚发生的进度,然后将该进度添加到到目前为止的运行进度计数中(例如,++_filesUnzippedSoFar)。
第一部分,找出工作的总规模,比较棘手。你基本上需要在运行解压缩之前运行解压缩:第一个,-l(这是一个小写的 L),是列出存档的内容;二是解压。第一个,您读取输出以确定存档包含多少文件/字节;第二个,您读取输出以确定进度条前进到的值。
设置进度条的属性很简单;这些实际上只是doubleValue 和maxValue。弄清楚你在工作中的位置是困难的部分,并且是非常特定于领域的——你需要阅读 unzip 的输出(两次,以不同的形式),理解它告诉你的内容,并将其转化为进度信息。
在 NSTask 中没有任何东西可以帮助你。 NSTask 的这一部分从standardOutput 属性开始和结束。它不知道 zip 文件、档案、档案内容甚至进度,因为这些都不适用于大多数任务。这一切都特定于你的任务,这意味着你必须编写代码来完成它。
【讨论】:
standardOutput 设置为 NSPipe,然后从管道的 fileHandleForReading 中读取。最好的读取方法是将文件句柄的readabilityHandler 设置为处理该输出块的块。另一种方法是 Parag Bafna 展示的:为 NSFileHandleReadCompletionNotification 添加一个观察者到本地通知中心,将文件句柄作为通知对象,并重复调用 readInBackgroundAndNotify——但这与基于块的 API 相比非常尴尬。