Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

EDIT: не вдаваясь в подробности, под ARC теперь вы можете добавлять блоки к коллекциям, как и любой другой объект (см. обсуждение).

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


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

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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