В ARC, блоки автоматически копируются при назначении на ivar напрямую?
Предположим, что следующий код под ARC,
typedef void (^MyResponseHandler) (NSError *error);
@interface MyClass : NSObject
{
MyResponseHandler _ivarResponseHandler;
}
- (void)myMethod:(MyResponseHandler)responseHandler
{
_ivarResponseHandler = responseHandler;
...
}
Вопрос. Является ли блок автоматически скопирован в кучу при присвоении ivar?
Мой предыдущий вопрос подразумевал, что он копируется при назначении через @property
. Но сегодня я использовал приведенный выше код и получил EXC_BAD_ACCESS
, который был исправлен путем изменения на
_ivarResponseHandler = [responseHandler copy]
.
Ответы
Ответ 1
Изменить: мой предыдущий ответ был, скорее всего, неправильным.
Некоторые выбранные выдержки из ARC docs говорят:
3. Сохраняемые указатели объектов
Сохраняемый указатель объекта (или сохраняемый указатель) - это значение типа сохраняемого типа объекта (сохраняемый тип). Существует три типа сохраняемых типов указателей объектов:
- указатели блоков (сформированные путем применения синтаксиса объявления каретки (^) к типу функции)
4.2. Семантика
Присвоение выполняется при оценке оператора присваивания. Семантика варьируется в зависимости от квалификации:
- Для объектов __strong новый указатель сначала сохраняется; во-вторых, lvalue загружается примитивной семантикой; в-третьих, новый указатель хранится в lvalue с примитивной семантикой; и, наконец, старый пункт был выпущен. Это не выполняется атомарно; внешняя синхронизация должна использоваться, чтобы сделать это безопасным в условиях одновременных нагрузок и хранилищ.
4.4.1. Объекты
Если объект объявлен с типом владельца сохраняемого объекта, но без явного классификатора прав, его тип неявно скорректирован, чтобы иметь квалификацию __strong.
7.5. Блоки
За исключением сохранения в качестве части инициализации переменной параметра __strong или чтения переменной __weak, всякий раз, когда эти семантики требуют сохранения значения типа указателя блока, он имеет эффект Block_copy. Оптимизатор может удалить такие копии, когда видит, что результат используется только в качестве аргумента для вызова.
Итак, я думаю, что ответ может быть, в зависимости от оптимизатора.
Ответ 2
Ваша проблема и решение указывают, что мой ответ на ваш другой вопрос, вероятно, был неправильным. Я основывал его на последнем параграфе раздела 7.5 clang Objective-C Автоматическая документация подсчета ссылок:
За исключением сохранений, выполняемых как часть инициализации переменной параметра __strong
или чтения переменной __weak
, всякий раз, когда эти семантики требуют сохранения значения типа блока-указателя, он имеет эффект Block_copy
, Оптимизатор может удалить такие копии, когда видит, что результат используется только в качестве аргумента для вызова.
Я взял "эту семантику" для обозначения всего документа, но если "эта семантика" относится только к разделу 7.5, тогда ARC только вставляет Block_copy
для блока, который захватывается блоком.
Ответ 3
Я надеюсь, что следующая ссылка может помочь вам понять Как хранить блоки в iVars??
http://nachbaur.com/blog/using-gcd-and-blocks-effectively