What data type do ivars for primitive properties have?

91 Views Asked by At

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?

2

There are 2 best solutions below

0
Sulthan On BEST ANSWER

When declaring a property BOOL cancelled the autosynthesized ivar is BOOL _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 _isCancelled actually means reading self->_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.

3
norders On

TL;DR: The same type as the property.

All object pointers and primitive types are scalar values - i.e. singular values. They all need to be stored at an address in memory and therefore they all have memory addresses of their own.

By passing &_isCancelled, you're passing the address of the BOOL variable, so the block() has been "let in on a secret" - i.e. the location of the BOOL - so it can update it. Then afterwards you're checking the resultant actual value of _isConnected. This works for primitive types (scalars) and object pointers (also scalars).

Whether its a property or not is irrelevant.