NSNotificationCenter with blocks considered harmful... unless you use weak references, then it's fine
· 1 minute read
Drew Crawford published a post entitled NSNotificationCenter with blocks considered harmful yesterday. Upon reading, one might get the impression that using the
NSNotificationCenter block API is different in some way then using blocks, well, anywhere else. It isn’t.
NSNotificationCenter retains the blocks that you pass to it, and as such, referencing
self inside the block will introduce in a nasty retain cycle. This is unfortunate but far from a new revelation; Jim Dovey wrote about this almost exactly two years ago and I got bit pretty hard myself during my earlier days as an iOS developer.
My problem is that Drew’s article seems to imply that using blocks with
NSNotificationCenter is worse in any way than using any other block that gets retained by
self. Either way, you need to make sure you’re not closing over a strong reference to
self or suffer the wrath of the resulting retain loop causing some hard-to-debug side effect. The only thing, in my opinion, that makes
NSNotificationCenter blocks slightly dicier is that as Drew points out, the normal LLVM warning is for some reason missing in this instance1.
This isn’t to say that Drew’s article isn’t worth reading; it’s a great read, and you’re almost certain to learn or have something reinforced. Just please know that using blocks at all requires understanding how to use weak references and the consequences of not doing so. I’d recommend reading the article but then following it up with the accompanying Hacker News comment thread, in which Ash Furrow far more eloquently sums up what I’ve been trying to explain with this post:
There’s nothing really magical about this – don’t cause retain cycles, everyone knows
__blocksemantics changed with ARC, keep the returned value from the block-based
NSNotificationCentermethod, etc. Standard stuff.
Originally published on cocoa.tumblr.com
Probably because unlike most blocks retain cycles, this one is caused by
NSNotificationCenterretaining the block as opposed to
selfretaining it. ↩