2

我正在尝试通过 NSTask 使用命令行实用程序压缩文件。

伪代码:

controller:
  init:
    register_self_as_observer_of_nstask_notifications

  startZip(file):
    file = somefileobject 
    task = "zip" with file path as argument
    task.launch

  notification_listener(notification):
    task = notification.get_object
    file = task.??? 

那么我怎样才能找出通知所属的文件对象呢?我通常使用 userInfo 字典来处理这些事情,但 NSTask 没有这样的选项。来自Apple Dev:此通知不包含 userInfo 字典。

谢谢!

4

2 回答 2

2

使用关联对象 API 将用户信息字典附加到任务实例。这将是最简洁的方法,但在 Mac OS X 10.6 引入关联对象 API 之前不能使用它。

或者,您可以使用从任务映射到用户信息的字典。创建从任务到用户信息的字典映射并不像听起来那么简单:

  • 您不能仅仅[taskInfoDict setObject:userInfo forKey:task]因为NSTask不符合NSCopying,而是NSDictionary依赖于复制其密钥。
  • 使用作为NSNumber任务对象的代理包装的进程标识符最有效。但是进程 ID 可以重复使用,并且任务在启动之前不会获得 PID。问题的根源是:你没有控制进程ID;底层操作系统可以。

使用任务对象的地址似乎是最好的解决方案:

[taskInfoDict setObject:userInfo forKey:[NSValue valueWithPointer:task]]

假设一个引用计数的环境,任务对象的地址将在其生命周期内保持稳定,并且它的生命周期完全在您的应用程序的控制之下。复制垃圾收集器会在此解决方案中引发麻烦,但在这种情况下,您可以使用可以直接处理指针的收集类 ( NSMapTable)。

于 2011-06-09T21:25:42.180 回答
1

考虑使用关联引用将文件 URL/路径关联到每个任务实例。每个对象可以有多个关联对象,每个关联对象都有一个对应的键,用于在需要时引用关联对象。

在您的控制器中,创建一个static表示文件 URL/路径键的变量:

static char fileURLKey;

创建NSTask实例时,将对应的文件 URL 关联到该实例:

NSURL *fileURL = …;
NSTask *task = …;
objc_setAssociatedObject(task, &fileURLKey, fileURL, OBJC_ASSOCIATION_RETAIN);

任务执行完成后,从通知对象中获取任务,然后从任务中获取文件 URL:

NSTask *task = [notification object];
NSURL *fileURL = (NSURL *)objc_getAssociatedObject(task, &fileURLKey);
于 2011-06-09T22:00:47.847 回答