Search code examples
objective-cautomatic-ref-countingblockweak-references

Blocks and objects with Strong Reference Cycle?


When you create an instance of a class, which has a block, it points to that block as a strong reference, and when you reference the object from that block it points to that object with a strong reference, which creates a strong reference cycle.

So if I were to do this:

__weak Employee *weakSelf = self;
myBlock = ^{
    NSLog(@"%@", weakSelf);
}

So now, the block has a weak reference to the object, but supposedly it's good practice to create a strong local reference to self inside the block in case the object that self points to is deallocated.

__weak Employee *weakSelf = self;
myBlock = ^{
    Employee *innerSelf = weakSelf;
    NSLog(@"%@", innerSelf);
}

I wanted to know and make sure that I understand this correctly, so I drew a picture of what I think is happening (If I'm wrong, please correct me): enter image description here

Or is this correct: enter image description here

A corrected visual would be greatly appreciated.


Solution

  • None of those are correct.

    There are just two objects here. An Employee object. And a block. That's it.

    You didn't show what myBlock is declared as, but assuming that it's an instance variable of Employee, then yes, by that assignment, the Employee object has a strong reference to the block.

    The block has a weak reference to the Employee object, because it captures the local variable weakSelf from the surrounding scope, and by capturing it, it makes an implicit "instance variable" in the block that has the same memory management characteristics as the captured variable (in this case, weak).

    The strongSelf inside the block is not relevant. It is just a local variable. Local variables are not instance variables, so they are not part of one object referencing another. Local variables only live for the duration of a particular invocation of the function. They do not cause cycles.

    The reason for innerSelf was so that the object pointed to (by weakSelf, which is the same object pointed to by self and innerSelf) is not deallocated in the middle of the function. This is only a problem if you were going to use weakSelf multiple times in the function, and rely on the states from those times to be consistent. By using innerSelf, it will make it consistently pointing to an existing object, or consistently nil. Since you only use weakSelf once here, it is not necessary.