Reputation: 3222
I'm having a problem of the right place to remove observer from NSNotificationCenter
// DetailOfSomethingViewController
@implementation DetailOfSomethingViewController
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(showMoreDetail:)
name:SOME_NOTIFICATION_NAME
object:sender];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)showMoreDetail:(id)sender {
[self presentViewController:[[MoreDetailViewController alloc] init] animated:NO completion:nil];
}
During my test run, I try to pop this viewController's instance from navigation stack and push new instance onto the stack. I found that the dealloc method of an instance that has been popped from navigation stack doesn't get called right away.
So, during that moment before dealloc gets called, if the SOME_NOTIFICATION_NAME has been sent out from its source, the popped instance still listening and responding by calling showMoreDetail (Note : the one on navigation stack works fine) and trying to present a MoreDetailViewController while not in the application window. So this warning has been raise.
Warning: Attempt to present <DetailOfSomethingController: 0xac2c3e0> on <MoreDetailViewController: 0xac268f0> whose view is not in the window hierarchy!
I can check for the existence on navigation stack of view controller instance but is there any proper way to remove observer right away when it got popped? I can't put the removal code in viewDidDisappear or viewWillDisappear since this controller has to be notify and do something even it's not the topViewController of the stack.
Also, adding the code to check before present another view has to be added several places inside this controller since showMoreDetail isn't the only method that will do the presentation, there are more similar methods.
Any help, suggestion are welcome.
Regards
Upvotes: 1
Views: 1166
Reputation: 620
My advice to you is to register your viewController as an observer in viewWillAppear: and remove it in viewWillDisappear:
That way your view will only respond when it's the top viewController.
UPDATE:
I think what you can do is register for that notification only when the view appears:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(showMoreDetail:)
name:SOME_NOTIFICATION_NAME
object:sender];
}
And do the same for removing your view controller as an observer (just for that notification and it would still listen to other notifications)
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:SOME_NOTIFICATION_NAME
object:nil];
}
Upvotes: 1
Reputation: 2495
In showMoreDetail:
check if the UINavigationController's topViewController
property equals self and if it does only then continue.
Upvotes: 1