Question

I thought I understood the usage of self in a block that is copied is a no no.

But in an attempt to clean my code i enabled a bunch of warnings in Xcode, one called "Sending messages to weak pointers"

so now in all my blocks, every time I use my created weakself reference __weak typeof(self) weakself = self;

I get this warning: Weak receiver may be unpredictably set to nil

a trivial example:

__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{

     [weakself doSomething]; //warning.

}];

I have seen answers which define a version of self within the block like so:

__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
     typeof(self) selfref = weakself; 
     [selfref doSomething]; //no warning.

}];

So I'm wondering what actually happens here:

  • Am I just tricking the compiler?
  • what does a strong reference to a weak reference do?
  • anything else I'm missing.

Thanks.

Was it helpful?

Solution

I thought I understood the usage of self in a block is a no no.

This is not strictly correct. Blocks retain the objects in them, so don't use self in a block if your block is retained by self.

For example, you can use self just fine in a UIView animation block. This is because your view controller (or whatever code is calling the animation) doesn't have a pointer to the UIView animation block.)

Am I just tricking the compiler?

No.

What does a strong reference to a weak reference do?

If the weak reference is not nil, the retain count of the receiver is increased. This will stop the object from being deallocated while you're using it.

Remember, ARC will deallocate objects when there are no longer strong references to them. By creating a strong reference inside the block, you're preventing possible deallocation until you're done with it.

anything else I'm missing.

I recommend reading the Practical Memory Management section of the Advanced Memory Management Programming Guide. Especially, read the subsection "Use Weak References to Avoid Retain Cycles".

OTHER TIPS

Remember that in ARC, an object will not be deallocated as long as there's a strong reference to it.

When an object has a weak reference, the object might be deallocated (if there's no other strong reference to the same object), so a weak reference doesn't ensure the objects life.

By doing this:

typeof(self) selfref = weakself; 

you're ensuring that you have a strong reference to that object before you use it (selfref is the strong reference pointing to the same object weakself is referring to). If you don't do this, the object could be deallocated while you use it.

Strong reference to a weak reference retains an object. It could be important in following case

__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{

     [weakself allocateSomething]; // (1)
     // ..... code (2)
     [weakself freeSomething];  // (3)
}];

If Weak receiver will be unpredictably set to nil in line (2) resources could be successfully allocated in (1) but not freed in (3). To avoid such problems strong reference could be used.

[aClass doSomethingInABlock:^{
     typeof(self) selfref = weakself; 
     [selfref allocateSomething]; // (1)
     // ..... code (2)
     [selfref freeSomething]; // (3)
}];

Now if selfref is not nil in (1) it will also be valid in (2) and (3).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top