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)?
__block __unsafe_unretained
modifiers suggested in Kevin's post may cause to the bad access exception in case of block executed in a different thread. It's better use only __block modifier for the temp variable and make it nil after the usage.Posting another answer because this was a problem for me too. I originally thought I had to use blockSelf anywhere there was a self reference inside a block. This is not the case, it is only when the object itself has a block in it. And in fact, if you use blockSelf in these cases the object can get dealloc'd before you get the result back from the block and then it will crash when it tries to call it, so clearly you want self to be retained until the response comes back.
First case demonstrates when a retain cycle will occur because it contains a block which is referenced in the block:
You don't need blockSelf in the second case because the calling object does not have a block in it that will cause a retain cycle when you reference self:
Just use:
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
You can use libextobjc library. It is quite popular, it is used in ReactiveCocoa for example. https://github.com/jspahrsummers/libextobjc
It provides 2 macros @weakify and @strongify, so you can have:
This prevents a direct strong reference so we don't get into a retain cycle to self. And also, it prevents self from becoming nil half-way, but still properly decrements the retain count. More in this link: http://aceontech.com/objc/ios/2014/01/10/weakify-a-more-elegant-solution-to-weakself.html
How about this?
I don't get the the compiler warning anymore.
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.