Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing BOOL within blocks

I am trying to set a flag using a BOOL within a block.

I declare the BOOL like this:

@property(nonatomic) BOOL flag;

And within the block:

__strong typeof(self) strongSelf = weakSelf;
if(strongSelf->_flag)

My question is, if I do:

__weak typeof(self) weakSelf = self;
if(weakSelf->_flag)

I would get an error:

"dereferencing a __weak pointer is not allowed die to possible null value caused by a race condition, assign it to strong variable first"

Can someone explain to me what this means?

In addition, it seems funny to me I have to reference the BOOL using __strong (i.e. strongSelf->_flag), would that be the same as using self->_flag, because I would be using a strong self here?


More over, if I declare the BOOL as an ivar instead of a property:

BOOL flag;

It would give me a warning also when I use it within the block:

if(flag)

And so I would need to do the following as well:

__strong typeof(self) strongSelf = weakSelf;
if(strongSelf->flag)

This baffles me, because normally we reference an ivar without self, just flag, but the above case seems to me that it is accessing the ivar like self->_flag.

??

I could have use something else such as a NSNumber and good riddance to all this, but my curiosity urges me not to turn a blind eye on it.

like image 389
Unheilig Avatar asked Jun 30 '26 19:06

Unheilig


1 Answers

I assume you scheduling the block operation in some operation queue or so when the block executes later in the future.

You should not assign self to weakSelf inside the block. You should do this outside the block

__weak typeof(self) weakSelf = self;
if(weakSelf->_flag)

__weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object. Apple arc docs.

You actually want your weakSelf be not null to do some stuff with it. To do so you must declare assign it to a variable with strong ownership qualifier. Sketch:

__weak id weakSelf = self;
schedule_block(^{
// at this point the object pointed by weakSelf may or may not be deallocated
id strongSelf = self; // after this point the object referenced by `strongSelf` will not be deallocated at least `strongSelf` to the end of current block
//You may safely work with `strongSelf` and be sure the object will live at least to the end of current block
});

To sum up: to be sure the object will not be deallocated while you work with it you should obtain a strong reference to it. On the other hand to prevent memory leaks you should use weak references. The algorithm looks like this:

  1. obtain weak reference to object of interest
  2. schedule block
  3. at the start of block obtain a strong reference
    1. if object still live - do whatever you need
    2. if object was deallocated earlier - skip operations in block

iVar is just a member of C-structure the compiler creates for the class at compile time. All references to ivars will be compiled to self-><ivar_name>.

You may refer to Apple's docs for details or to LLVM specs on ARC or LLVM specs on blocks

like image 68
Max Komarychev Avatar answered Jul 03 '26 07:07

Max Komarychev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!