When I use -addObserverForName: object: queue: usingBlock:
for NSNotificationCenter
in the -viewDidLoad:
method of my view controller, the -dealloc
method ends up not being called.
(When I remove -addObserverForName: object: queue: usingBlock:
, -dealloc
is called again.)
Using -addObserver: selector: name: object:
doesn't seem to have this problem. What am I doing wrong? (My project is using ARC.)
Below is an example of my implementation, in case I'm doing something wrong here:
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
updateResult = YES;
}];
Thanks in advance for any help.
I've tried adding the following (to no avail):
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isMovingFromParentViewController]) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
updateResult
is an instance variable which prevents the object from being deallocated as it is retained by that block.In other words, you got a retain cycle. The object retains the block and the block retains the object.
You will need to create a weak or unsafe_unretained reference to that instance and its variable for loosing that relationship.
Add the following prior to your notification block:
or (in case you are on iOS5 and above)
Then, within that block, reference the object via that new weak reference:
Please note that retain-cycles are not a bad thing per se. Sometimes you actually want them to happen. But those are instances where you are certain that the cycle will be broken after a specific time (e.g. Animation Blocks). The cycle is broken once the block has executed and is removed from the stack.
This is not retain cycle.
NSNotificationCenter
hold the block, block is holdself
. Because[NSNotificationCenter defaultCenter]
is a singleton living in all app life cycle, So it holdself
indirect.This is very likely because you have a retain cycle.
This is typically the case when your block implicitly retain self, and self retains the block in a way. You will have a retain cycle as each one retains the other one, and their retainCount thus never reach zero.
You should activate the warning
-Warc-retain-cycles
that will warn you about such issues.So in your case, you are using the variable
updateResult
, which I assume is an instance variable, and this implicitly retainself
. You should instead use a temporary weak variable to represent self, and use this in your block, so that it does not get retained and you break the retain cycle.