(1) Your code is wrong (incomplete). When you issue addObserverForName:
you must capture the returned value; this is the observer token. You store this somewhere (e.g. an instance variable):
self->observer = [[NSNotificationCenter defaultCenter]
addObserverForName:@"woohoo" object:nil queue:nil
usingBlock:^(NSNotification *note)
{
//whatever
}];
Later, when you're going out of existence, you remove that observer token from the notification center by calling removeObserver:
with that token as argument. If you don't do that, you can crash later.
[[NSNotificationCenter defaultCenter] removeObserver:self->observer];
(2) But wait, there's more! Under ARC, when the block is copied, you'll get a retain cycle. This is because the stored observer token contains the block and is itself retaining self. I will give you three ways to break this retain cycle:
(a) Store the observer token as a weak reference:
__weak id observer;
(b) Store the observer token as a strong reference, but explicitly release it (by nilifying it) when you remove the observer:
[[NSNotificationCenter defaultCenter] removeObserver:self->observer];
self->observer = nil; // crucial
(c) Do the "weak-strong dance", like this, when you create the block (I am pretending that self
is a FlipsideViewController):
__weak FlipsideViewController* wself = self;
observer = [[NSNotificationCenter defaultCenter]
addObserverForName:@"user.login"
object:nil queue:nil usingBlock:^(NSNotification *note) {
FlipsideViewController* sself = wself;
[sself dismissModalViewControllerAnimated:YES];
}];
Now, you might think that the "weak-strong dance" is an extreme approach, as one of my commenters implies. But it has one huge advantage: it is the only one of these three solutions that allows you to remove the observer in dealloc
. With the other two solutions, dealloc
will never be called until after you have called removeObserver:
- and finding a better place to call it may not be easy.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…