Possible locations to call addObserver and removeObserver methods
Asked Answered
O

3

8

I have a case where the child view sends notification to its parent view. Now I'm calling addObserver: in viewWillAppear: and removeObserver: in viewWillDisappear:. But, I'm guessing this is not correct since viewWillAppear: calls when view is refreshed.

[[NSNotificationCenter defaultCenter] addObserver: (id)observer selector: (SEL)aSelector name: (NSString *)aName object: (id)anObject];

[[NSNotificationCenter defaultCenter] removeObserver: (id)observer name: (NSString *)aName object: (id)anObject];

Thanks.

Overexcite answered 1/1, 2009 at 4:31 Comment(0)
S
5

Actually, this is a bad idea. When memory gets low, your view controller may get sent a memory warning. The default behavior in this instance is to clear out your view (if you're not currently on screen). In this case, you could get the viewDidLoad message sent a second time (after the memory event, when your view is brought back on screen by its navigation controller.) Thus you'll have two registrations of the same object, but only one removal (in its dealloc)

A better solution is either to set a flag saying you've registered, or to register in your init method.

Stott answered 1/1, 2009 at 13:13 Comment(4)
is it true that dealloc is not always called? Would it be safer to call addObserver in init and call removeObserver in viewDidUnload - or this scheme would cause my view controller not to re-register after it is loaded once again after memory warning (which caused the view to get unloaded since it was not shown)?Brecciate
Still not clear on where to put the removeObserver in this case.Declass
Wouldn't it be better to addObserver in ViewWillAppear, removeObserver in ViewWillDisappear? So the observer would only be around as long as it is needed. And add/remove calls will always be balanced, AFAIK.Platonic
I'm guessing the possibility of 'getting low memory' is very low in 2017. So that shouldn't be an issue. However what if init was too early, ie you wanted to observer for something UI related and need your view to be loaded?Ppm
O
1

I guess the correct positions to register for notification is viewDidLoad method, and correct position to unregister for same notifications is dealloc method.

Overexcite answered 1/1, 2009 at 8:31 Comment(3)
But when receive memory warning, viewDidUnload will be called but not dealloc, when nav back to this viewcontroller, viewDidLoad will be called again, then, your notice register again.Makeyevka
You're right. This post is very old, so ignore it. The important thing is to balance the register and unregister calls. Either use viewDidLoad and viewDidUnload, or viewDidLoad (with flag) and dealloc, or init and dealloc for registering and unregistering your notifications. See Ben Gottlieb's comment for relevant information.Overexcite
Don't know if it's right either, but I do it your way. And remember that viewDidUnload is deprecated since iOS 6.0...Humanoid
C
0

Ben's right - but I found another, potentially fragile, way around that. I just discovered this because I was forever getting the "...was deallocated while key value observers were still registered with it"

I don't know why - but when I had addObserver in my init method, and removeObserver in my dealloc method - I was still getting the KVO was still being observed message. I stepped through and verified that my removeObserver was being called correctly.

I moved my addobserver into the viewDidLoad method instead, and that seemed to work.

I left a removeObserver in viewDidUnload and in dealloc; but I don't like that because it's not balanced. But under normal circumstances, my viewDidUnload doesn't get called - this is just protection in case I get a low memory notification.

But I can see potentially getting into the situation where a low memory event comes in, viewDidUnload gets called. If I then hit dealloc sometime after that (before I hit viewDidLoad again), I will call removeObserver twice!

So, I think I'll just keep it in my viewDidLoad, and my dealloc.

I still don't know why it doesn't work right if I do the addobserver in my init method.

Cinematograph answered 2/3, 2012 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.