views:

19

answers:

3

I have a navigation controller. One of the views adds custom subviews in its viewDidAppear:. I notice that the first time I navigate to an instance of this view controller after launching the app, viewDidAppear: invokes twice. If I pop this view off the stack and navigate to it again, viewDidAppear: invokes only once per appearance. All subsequent appearances invoke viewDidAppear: once.

The problem for me is that the first time I get to this view I end up with twice the number of subviews. I work around this problem by introducing a flag variable or some such, but I'd like to understand what is happening and how come I get two invocations in these circumstances.

A: 

maybe you invoke viewDidAppear in viewDidLoad (or some other stuff is going on there), since it's invoked only once during loading the view from the memory. It would match, that it's invoked two times only the first time.

Alistra
That was my first thought. But no, I'm not doing that. And if I set a breakpoint to see the on `viewDidAppear:`invocation, none of my own methods appear in it.
iter
A: 

You definitely should provide more info.

Is this the root view controller?
Maybe you initiate the navigation controller with this root view controller and then push it to the navigation controller once again?

Michael Kessler
Interesting idea, but no, I'm not pushing it twice. I `NSLog(@"%@", [[self navigationController] viewControllers]);` from `viewDidAppear` and see one instance of my view sitting on top of root view.
iter
Maybe you have 2 navigation controllers by mistake?
Michael Kessler
A: 

You should never rely on -viewWillAppear:/-viewDidAppear: being called appropriately balanced with the disappear variants. While the system view controllers will do the best they can to always bracket the calls properly, I don't know if they ever guarantee it, and certainly when using custom view controllers you can find situations where these can be called multiple times.

In short, your -viewWillAppear:/-viewDidAppear: methods should be idempotent, meaning if -viewDidAppear: is called twice in a row on your controller, it should behave properly. If you want to load custom views, you may want to do that in -viewDidLoad instead and then simply put the on-screen (if they aren't already) in -viewDidAppear:.

You could also put a breakpoint in your -viewDidAppear: method to see why it's being called twice the first time it shows up.

Kevin Ballard
I have a breakpoint in `viewDidAppear:`. How can it answer the why question?
iter
Look at the stack trace to find out why the system is calling this method. If the backtrace is different for both of the calls, you can use this to try and figure out what's going on. This may or may not be useful though, depending on precisely what is contained in the backtrace.
Kevin Ballard
The stacks look identical, hence my surprise at your suggestion. My solution is to refactor the code so I can call the code in `viewDidAppear:` indirectly from `viewDidLoad:`, and so avoid the whole issue. I'm accepting your answer even though the double invocation is still a mystery to me.
iter