I recently learned another important newbie lesson about viewDidLoad:
: it may be called multiple times during your application’s lifetime for any given UIViewController
if its view is ever hidden and shown during low-memory situations.
Here’s the story: I am currently making a monkey app which features a single monkey. It was running fine in the simulator, but sometimes when I ran it on the device, an extra monkey was spawned every time I switched between the main view and the settings view! A couple of view switches and I’d have a bunch of monkeys onscreen, which was amusing but also very slow and not what was intended. Who was making the new monkeys?
My first iPhone test apps did a lot of initialization in viewDidLoad:
. It makes sense because it is called right after a view has finished loading from its nib, and it feels like a good time to do your final initialization of things since the system has basically done everything it needs to do to display a window.
What I forgot was that the default behaviour of UIViewController didReceiveMemoryWarning
is to release its view if it’s currently hidden (due to navigation, say). All well and good. But when the view becomes visible again, the view will be reloaded from its nib, and viewDidLoad:
will be called again.
This is why I kept getting new monkeys: I was making the monkey in my MainViewController
‘s viewDidLoad:
. When I switched to the settings view when memory was short, the MainViewController
purged its view. Switching back to the main view caused the MainViewController
to reload the view from the nib, thus calling viewDidLoad:
again, and thus creating another monkey.
So, any initialization code that goes into viewDidLoad:
should make sense in that situation: i.e. view-specific stuff when recreating the UIView object, not application-level initialization stuff. Or, if your app-level initialization stuff needs a view to be loaded before running, then at least check to make sure that it hasn’t run already.