2017-01-25 12 views
0

Я спрашиваю, потому что я занимался сложным блочным кодом, и я не ожидал, что следующий код будет работать правильно.Какие типы данных имеют ivars для примитивных свойств?

Скажем, у нас есть свойство BOOL, как это:

@property (nonatomic, assign) BOOL isCancelled; 

Это автоматический синтезирован, нет пользовательских добытчик, не сеттер, никаких явных Ивар.

Тогда есть этот код ... который отлично работает

dispatch_async(queue, ^{ 
    id result = block(&_isCancelled); 
    if (!_isCancelled) { ... } 
} 

Однако, я бы ожидал, что он работает для блока() вызов, но не для, если, где я думал, что это будет захватить значение _isCancelled и сохранить его const, а не изменять его во время исполнения. Тем не менее, во время выполнения значение _isCancelled всегда согласовано внутри/вне блока, как если бы оно было фактически BOOL *

Может ли кто-нибудь объяснить, что происходит?

+0

В данном коде не используется какое-либо свойство, '_isCancelled' является нормальным * ivar *, хотя и объявлено неявным образом. – Sulthan

+0

Согласен, но поскольку он не объявлен явно, я мог предположить, что он будет объявлен как указатель вместо примитива. Это может объяснить поведение (если я что-то не хватает) – CatalinM

+0

Тип свойства совпадает с типом поддержки ivar. Объявление свойства 'BOOL isCancelled' означает, что будет синтезирован ivar' BOOL _isCancelled'. Это все. – Sulthan

ответ

0

При объявлении имущества BOOL cancelled автосинтезировано ivar is BOOL _isCancelled. Это примитивная переменная, а не указатель.

Однако, когда блок захватывает ивары, он фактически захватывает self, а не сам ivar. Reading ivar _isCancelled на самом деле означает чтение self->_isCancelled.

Следовательно, ivars не фиксируются по значению, если вы сначала не сохранили их в локальной переменной (например, BOOL isCancelled = _isCancelled).

Для получения дополнительной информации см. Block automatic retaining, does it affect even to ivars in self?.

0

TL; DR: тот же тип, что и собственность.

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

Пропустив &_isCancelled, вы пропускание адреса переменной BOOL, поэтому block() был «пусть по секрету» - то есть по месту нахождения BOOL - так что он может обновить его. Затем после этого вы проверяете полученный результат значение _isConnected. Это работает для примитивных типов (скаляров) и указателей объектов (также скаляров).

Независимо от того, является ли оно его собственностью или нет.

+0

Вот и я, хотя. Я ожидал, что '_isCancelled' неизменен внутри блока (поскольку он рассматривает все vars внутри области как _const_, поэтому он всегда будет иметь значение, которое было у него при оценке блока). Тем не менее, я подозреваю, что это поведение связано с тем, что '_Connected' является глобальным и не является локальным. – CatalinM

+0

Значение, которое вы передаете в _is_ const - это адрес BOOL. Ничто не меняется, кроме блока кода, буквально меняющего некоторые биты по этому адресу. Внутри блока эта переменная не является BOOL, это указатель на BOOL. – norders

+0

Моя проблема заключалась в том, если бы это произошло после выполнения внутреннего блока. Однако теперь я понимаю, что 'self' фактически сохраняется, даже если напрямую не ссылаться. – CatalinM

 Смежные вопросы

  • Нет связанных вопросов^_^