I am asking because the I was dabbling into some complicated block code and I did not expect the following code to work properly.
Say we have a BOOL property, as so:
@property (nonatomic, assign) BOOL isCancelled;
It's auto synthesised, no custom getter, no setter, no explicit ivar.
Then, there's this code... which works perfectly
dispatch_async(queue, ^{
id result = block(&_isCancelled);
if (!_isCancelled) { ... }
}
However, I would have expected it work for the block() call, but not for the if, where I thought it would capture the value of _isCancelled and keep it const, not have it mutate throughout execution. Still, at runtime, the value of _isCancelled is always consistent inside/outside the block, as if it were actually BOOL *
Can anyone explain what's going on?
When declaring a property
BOOL cancelledthe autosynthesized ivar isBOOL _isCancelled. This is a primitive variable, not a pointer.However, when a block is capturing ivars, it is actually capturing
self, not the ivar itself. Reading ivar_isCancelledactually means readingself->_isCancelled.Therefore, ivars are not captured by value unless you save them into a local variable first (e.g.
BOOL isCancelled = _isCancelled).See Block automatic retaining, does it affect even to ivars in self? for more information.