Notification Block Retain Cycle
Mon, 17 Dec 2012 09:06:36 -0800 Post Comments
The ARC migration docs ( http://developer.apple.com/library/mac/#releasenotes/Objecti[..] ) recommend the following pattern (which I've extended to your situation):
@implementation MYObject
{
id observerReference;
}
- (id)init
{
if ((self = [super init]))
{
__weak MYObject *weak_self = self;
observerReference = [[NSNotificationCenter defaultCenter] addObserverForName:MYCoolNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^ (NSNotification *note) {
MYObject *strong_self = weak_self;
if (strong_self) {
[strong_self someMethod];
strong_self->someIvar = someValue;
}
}];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:observerReference];
}
@end
This prevents the block from taking a retain on "self" by having it capture a weak reference instead, which breaks the retain cycle. The subsequent assign to and use of "strong_self" prevents the weak reference from being deallocated out from under you during the block's execution. As a consequence, you must not refer to "self" within the block, even implicitly by ivar access. Methods called by the block can continue to refer to self normally. This code is thread-safe for the effects observable here (though obviously I can't say anything about what your notification handler is actually doing).
-- Gwynne Raskind
@implementation MYObject
{
id observerReference;
}
- (id)init
{
if ((self = [super init]))
{
__weak MYObject *weak_self = self;
observerReference = [[NSNotificationCenter defaultCenter] addObserverForName:MYCoolNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^ (NSNotification *note) {
MYObject *strong_self = weak_self;
if (strong_self) {
[strong_self someMethod];
strong_self->someIvar = someValue;
}
}];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:observerReference];
}
@end
This prevents the block from taking a retain on "self" by having it capture a weak reference instead, which breaks the retain cycle. The subsequent assign to and use of "strong_self" prevents the weak reference from being deallocated out from under you during the block's execution. As a consequence, you must not refer to "self" within the block, even implicitly by ivar access. Methods called by the block can continue to refer to self normally. This code is thread-safe for the effects observable here (though obviously I can't say anything about what your notification handler is actually doing).
-- Gwynne Raskind
