NSTask: Как получить контекст после заключения, так как словарь userInfo не предоставляется? - PullRequest
2 голосов
/ 10 июня 2011

Я пытаюсь заархивировать файлы с помощью утилиты командной строки через 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.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 10 июня 2011

Используйте API связанного объекта, чтобы присоединить пользовательский информационный словарь к экземпляру задачи. Это было бы самым чистым подходом, но его нельзя использовать до введения API связанного объекта в Mac OS X 10.6.

Кроме того, вы можете использовать словарь, который отображается от задачи к информации пользователя. Создание отображения словаря из задачи в пользовательскую информацию не так просто, как кажется:

  • Вы не можете просто [taskInfoDict setObject:userInfo forKey:task], потому что NSTask не соответствует NSCopying, но NSDictionary полагается на копирование его ключей.
  • Использование идентификатора процесса, заключенного в NSNumber в качестве прокси для объекта задачи, в основном работает. Но идентификаторы процессов можно использовать повторно, и задача не получает PID до тех пор, пока она не будет запущена. Корень проблемы: вы не контролируете идентификатор процесса; базовая ОС делает.

Использование адреса объекта задачи представляется наилучшим решением:

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

В предположении среды с подсчетом ссылок адрес объекта задачи будет стабильным в течение всего времени его существования, а его время жизни полностью контролируется вашим приложением. В этом решении копирующий сборщик мусора может вывести гаечный ключ, но в этом случае вы можете использовать класс коллекции, который может обрабатывать указатель напрямую (NSMapTable).

1 голос
/ 10 июня 2011

Попробуйте использовать ассоциативные ссылки , чтобы связать 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);
...