Tar_Tw45
Tar_Tw45

Reputation: 3222

popViewController, dealloc and removeObserver

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

Answers (2)

Mariam K.
Mariam K.

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

Devfly
Devfly

Reputation: 2495

In showMoreDetail: check if the UINavigationController's topViewController property equals self and if it does only then continue.

Upvotes: 1

Related Questions