it-swarm.com.ru

Хранение блоков в массиве

В Objective-C я знаю, что блоки считаются объектами, поэтому мне было интересно, можно ли их хранить в массиве. Возникает вопрос, являются ли блоки первоклассными объектами или они просто обрабатываются как объекты ради передачи их между объектами? Если они являются объектами первого класса, то не должны ли они храниться в массивах?

50
noizetoys

РЕДАКТИРОВАТЬ: не вдаваясь в подробности, в ARC теперь вы можете добавлять блоки в коллекции, как и любой другой объект (см. Обсуждение).

Я оставил оригинальный ответ без изменений, так как он содержит некоторые интересные технические детали.


Возникает вопрос, являются ли блоки первоклассными объектами или они просто обрабатываются как объекты ради передачи их между объектами? Если они являются объектами первого класса, то не должны ли они храниться в массивах?

Блоки - это объекты Objective-C, которые очень похожи на любой другой объект NSO, с несколькими ключевыми отличиями:

  • Блоки всегда генерируются компилятором. Они эффективно "alloc/init" редактируются во время выполнения, поскольку выполнение проходит через объявление блоков.

  • Блоки изначально создаются в стеке. Block_copy () или метод copy должны использоваться для перемещения блока в кучу, если блок должен пережить текущую область (см. Точку ARC ниже).

  • У блоков на самом деле нет вызываемого API помимо управления памятью.

  • Чтобы поместить блок в коллекцию, его сначала нужно скопировать Всегда. В том числе под ARC.  (См. Комментарии.) Если вы этого не сделаете, существует риск того, что выделенному стеку блоку будет autoreleased, и ваше приложение позже будет аварийно завершено.

  • Копирование блока на основе стека также скопирует все захваченное состояние. Если вы делаете несколько копий блока, более эффективно скопировать его один раз, а затем скопировать копию (потому что копирование копии просто увеличивает количество сохраняемых элементов, поскольку блоки являются неизменяемыми).

  • В ARC возвращение блока из метода или функции "просто работает"; оно будет автоматически скопировано в кучу, и возвращение будет автоматически освобожденным блоком (компилятор может оптимизировать автоматическое освобождение при определенных обстоятельствах). Даже с ARC вам все равно нужно скопировать блок, прежде чем поместить его в коллекцию.

Я написал пару постов в блогах, в которых содержится введение в блоки и некоторые советы и рекомендации . Вы можете найти их интересными.

И да, добавление их в словари весьма полезно. Я написал пару кусочков кода, где я помещал блоки в словари как обработчики команд, где ключом было имя команды. Очень кстати.

90
bbum

Да, блоки действительно являются объектами, и вы можете поместить их в массивы:

NSMutableArray *arr = [NSMutableArray new];
[arr addObject:^(){NSLog(@"my block");}];
void (^ myblock)() = [arr objectAtIndex:0];
myblock();

это поместит "мой блок" в консоль.

39
Eduardo Scoz