NSTask:由于没有提供 userInfo 字典,如何在结论时获取上下文?

发布于 2024-11-14 15:29:09 字数 642 浏览 4 评论 0原文

我正在尝试通过 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 字典。

谢谢!

I'm trying to zip files using the command-line utility through NSTask.

pseudocode:

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.??? 

So how can I find out which file object the notification pertains to? I usually use the userInfo dictionary for such things, but NSTask has no such option. From Apple Dev: This notification does not contain a userInfo dictionary.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风筝在阴天搁浅。 2024-11-21 15:29:09

使用关联对象 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)。

Use the associated object API to attach a user info dictionary to the task instance. This would be the cleanest approach, but it cannot be used prior to the introduction of the associated object API with Mac OS X 10.6.

Alternatively, you can use a dictionary that maps from task to user info. Creating a dictionary mapping from task to user info is not as straightforward as it sounds:

  • You can't just [taskInfoDict setObject:userInfo forKey:task] because NSTask does not conform to NSCopying, but NSDictionary relies on copying its keys.
  • Using the process identifier wrapped as an NSNumber as a proxy for the task object mostly works. But process IDs can be reused, and a task doesn't get a PID till after it's been launched. The root of the problem is: You don't control the process ID; the underlying OS does.

Using the address of the task object seems to be the best solution:

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

Assuming a reference-counted environment, the task object's address will be stable for its lifetime, and its lifetime is entirely under control of your application. A copying garbage collector would throw a wrench in this solution, but in that case, you could use a collection class that can handle the pointer directly (NSMapTable).

天荒地未老 2024-11-21 15:29:09

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

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

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);

Consider using associative references to associate the file URL/path to each task instance. Every object can have multiple associated objects, and each associated object has a corresponding key that is used to reference the associated object when needed.

In your controller, create a static variable that represents the file URL/path key:

static char fileURLKey;

When creating an NSTask instance, associate the corresponding file URL to that instance:

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

When the task has finished executing, get the task from the notification object and then get the file URL from the task:

NSTask *task = [notification object];
NSURL *fileURL = (NSURL *)objc_getAssociatedObject(task, &fileURLKey);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文