Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ARC __block and __weak

Let's say I'm trying to access self from within a block:

[someObject successBlock:^(NSArray *result) {
    [self someSuccessMethod];
} failure:^(NSString *errorMessage, int status) {
    [self someFailureMethod];
}];

I understand that this creates a retain cycle and that someObject and self never get de-alloced.

What's confusing me is what actually happens with/without the __block keyword. I can fix the retain cycle by making a __weak reference to self:

__weak MyClass* me = self;
[someObject successBlock:^(NSArray *result) {
    [me someSuccessMethod];
} failure:^(NSString *errorMessage, int status) {
    [me someFailureMethod];
}];

I don't need to use __block here, because I'm not trying to modify me from within the block. From what I understand, if I don't use __block, a copy of me is referenced inside the block. My question is: if what's being referenced inside the block is just a copy of the object, why does the original code block create the retain cycle? I would guess that the reference to self is just a copy, since I'm never using the __block keyword. Am I thinking about this incorrectly?

like image 681
hodgesmr Avatar asked Jul 23 '13 14:07

hodgesmr


1 Answers

In the first case, the block captures self, i.e. it saves a copy of self as another strong pointer. That increases the retain count of the pointed-to object, and causes the retain cycle.

In the second case, the block captures me, i.e. it saves a copy of me as another weak pointer. That does not increase the retain count and therefore causes no retain cycles.

(If you print the address of me outside and inside the block, you will see that the addresses are different. The block has its own weak pointer to the object.)

If the pointed-to object is deallocated, all weak references (including the one saved by the block) are set to nil by the Objective-C runtime.

(I just hope that I got this right.)

like image 163
Martin R Avatar answered Sep 17 '22 15:09

Martin R