Управление памятью с блочным программированием в Objective C - PullRequest
5 голосов
/ 20 мая 2011

Я читал следующую документацию Apple по блоку завершения в очередях отправки, и у меня возникли проблемы с пониманием ее части. В документе упоминается, что «для предотвращения преждевременного освобождения очереди крайне важно сохранить эту очередь первоначально и освободить ее после отправки блока завершения». Это противоречит моему пониманию того, что блок сохраняет все переменные в своем закрытии, что упоминается в Руководстве по программированию блока.

Что мне здесь не хватает? Фрагмент из документа вставлен ниже:

Блок завершения - это просто еще один фрагмент кода, который вы отправляете в очередь в конце своей исходной задачи. Код вызова обычно предоставляет блок завершения в качестве параметра при запуске задачи. Все, что должен сделать код задачи, это отправить указанный блок или функцию в указанную очередь, когда он завершит свою работу.

В листинге 3-4 показана функция усреднения, реализованная с использованием блоков. Последние два параметра функции усреднения позволяют вызывающей стороне указывать очередь и блок для использования при сообщении результатов. После того, как функция усреднения вычисляет свое значение, она передает результаты в указанный блок и отправляет его в очередь. Чтобы предотвратить преждевременное освобождение очереди, важно сначала сохранить эту очередь и освободить ее после отправки блока завершения. Перечисление 3-4, Выполняющее обратный вызов завершения после задачи

void average_async(int *data, size_t len, dispatch_queue_t queue, void (^block)(int))
{
   // Retain the queue provided by the user to make
   // sure it does not disappear before the completion
   // block can be called.
   dispatch_retain(queue);

   // Do the work on the default concurrent queue and then
   // call the user-provided block with the results.
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   int avg = average(data, len);
   dispatch_async(queue, ^{ block(avg);});

   // Release the user-provided queue when done
   dispatch_release(queue);
   });
}

1 Ответ

3 голосов
/ 20 мая 2011

Это противоречит моему пониманию того, что блок сохраняет все переменные в своем закрытии

Это не противоречие, а недоразумение. Блок сохраняет все объекты target-c , на которые он ссылается. Другие типы объектов используют свои собственные функции сохранения вместо стандартной. Следовательно, среда выполнения не может знать, как сохранить каждую переменную, которую может содержать блок. Вот почему очередь нужно сохранять и освобождать вручную.

...