2

I have a simple viewController that I want to listen for UIKeyboardWillHideNotification. Therefore I have the following code:

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void) keyboardWillBeHidden
{
    [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}

I'm trying to decide when to remove the viewController as an notification center observer. I only need to know about the UIKeyboardWillHideNotification when the viewcontroller is on screen, thus I'm thinking about adding the following:

- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Is this sufficient? Is there ever a chance that viewDidUnload or dealloc will get called while the viewController is still on screen? Note that I'm using a very basic UINavigationController for the flow of my app.

Nosrettap
  • 10,940
  • 23
  • 85
  • 140

2 Answers2

5

Registering the notification in viewWillAppear and unregistering it in viewWillDisappear seems to be a clean and symmetric solution to me.

Note that viewWillAppear can be called multiple times before dealloc (e.g. if another view controller is pushed onto your VC, or if you switch between tab bar controllers.) If you register the notification in viewWillAppear and unregister it only in dealloc then you will get duplicate registrations (compare Warning for iOS/iPhone users about duplicate NSNotification observations) and the registered selector is called multiple times for a single notification event.

I actually prefer the block-based observer registration method

addObserverForName:object:queue:usingBlock:

which returns an opaque object which is used for removing the observer again. Storing this return value into an instance variable of your view controller helps to keep track if the observer is already registered or not, and therefore helps to avoid duplicate registrations.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • So when you use the `addObserverForName` method, would I still put it in `viewWillAppear` and `viewWillDisapper`? – Nosrettap Mar 30 '13 at 19:56
  • @Nosrettap: Yes. So in this case it does not make a big difference, I just mentioned this as a general remark for more complicated situations. And I like the block-based methods! – Martin R Mar 30 '13 at 19:59
  • @MartinR do you have an example of an implementation with `addObserverForName:object:queue:usingBlock:`? Many Thanks – Ríomhaire May 05 '16 at 16:59
0

To answer your direct question, dealloc will never be called while your view is still on screen unless you directly call it which you shouldn't be.

dealloc will only be called when there are no strong pointers remaining that point to your viewController.

As Anoop Vaidya suggests, it is totally doable to put removeObserver in dealloc and be confident that dealloc won't get called while your viewController is on screen, and if it does... well you have much bigger problems than removing an observer

Edit: Since I can't actually reply to comments yet, when your viewController is off screen it is actually deallocated. It is then re-instantiated when it is called back on screen.

Edit: I'm wrong

Pinwheeler
  • 1,061
  • 2
  • 13
  • 26
  • A view controller is *not* automatically deallocated and re-instantiated when it's off-screen. It's also quite possible to deallocate a view controller while its view is on screen because the view doesn't have a strong reference to its view controller. This shouldn't happen normally, especially with ARC, but if you were to manually add a vc's view to the hierarchy, it can happen quite easily if the vc is autoreleased. – omz Mar 30 '13 at 19:29
  • @omz: I do not understand your second sentence. How could it happen that a view controller is deallocated while its view is still visible? Shouldn't there be strong references to the view controller while it is somewhere in the view controller hierarchy? - OK, I just saw your update to the comment. I was only thinking in ARC. – Martin R Mar 30 '13 at 19:33
  • Mah bad, I thought I heard that in the Stanford lectures but I am still mostly noob – Pinwheeler Mar 31 '13 at 02:08