Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retain cycle on `self` with blocks

I'm afraid this question is pretty basic, but I think it's relevant to a lot of Objective-C programmers who are getting into blocks.

What I've heard is that since blocks capture local variables referenced within them as const copies, using self within a block can result in a retain cycle, should that block be copied. So, we are supposed to use __block to force the block to deal directly with self instead of having it copied.

__block typeof(self) bself = self;
[someObject messageWithBlock:^{ [bself doSomething]; }];

instead of just

[someObject messageWithBlock:^{ [self doSomething]; }];

What I'd like to know is the following: if this is true, is there a way that I can avoid the ugliness (aside from using GC)?

like image 786
Jonathan Sterling Avatar asked Oct 11 '22 06:10

Jonathan Sterling


2 Answers

Strictly speaking, the fact that it's a const copy has nothing to do with this problem. Blocks will retain any obj-c values that are captured when they are created. It just so happens that the workaround for the const-copy issue is identical to the workaround for the retain issue; namely, using the __block storage class for the variable.

In any case, to answer your question, there's no real alternative here. If you're designing your own block-based API, and it makes sense to do so, you could have the block get passed the value of self in as an argument. Unfortunately, this doesn't make sense for most APIs.

Please note that referencing an ivar has the exact same issue. If you need to reference an ivar in your block, either use a property instead or use bself->ivar.


Addendum: When compiling as ARC, __block no longer breaks retain cycles. If you're compiling for ARC, you need to use __weak or __unsafe_unretained instead.

like image 170
Lily Ballard Avatar answered Oct 12 '22 19:10

Lily Ballard


Just use:

__weak id weakSelf = self;

[someObject someMethodWithBlock:^{
    [weakSelf someOtherMethod];
}];

For more information: WWDC 2011 - Blocks and Grand Central Dispatch in Practice.

https://developer.apple.com/videos/wwdc/2011/?id=308

Note: if that doesn't work you can try

__weak typeof(self)weakSelf = self;
like image 68
3lvis Avatar answered Oct 12 '22 19:10

3lvis