views:

1059

answers:

2

I'm trying to figure out what logic should go into the different UIViewController methods like viewDidLoad, viewDidAppear, viewWillAppear, ...

The structure of my app is that I have a root view controller that doesn't really have a view of its own, rather it has a tab view controller and loads other view controllers into it. But in the future, it may have to load other view controllers instead of the tab bar controller depending on app logic.

My main question is, what do people usually put into the viewDidLoad, .... methods.

Currently I:

viewDidLoad - setup the tab bar controller and set its view to the view controller's own view

viewDidAppear - check if user has stored login info if not - present with login if so, login and get app data for first tab

I'm trying to figure out now if my logic for setting up my tab bar controller should go into loadView rather than viewDidLoad.

Any help would be great. Small examples found on the web are great, but they don't go into detail on how larger apps should be structured.

A: 

viewDidLoad will be called once per lifetime of each UIViewController's view. You put stuff in there that needs to be set up and working before the user starts interacting with the view.

viewDidAppear is called whenever the view has appeared to the user. It could potentially be called more than once. An example would be the root screen of an app using a UINavigationController to push and pop a hierarchy of views. Put stuff in there that you'd want done every time. For example, you might want to hide the UINavigationBar of the root screen, but show it for all subscreens, so you'd do the hiding of the bar here.

Therefore, you'd put your logic for setting up your UITabBarController in viewDidLoad, since it only should be done once.

Regarding your app, is there a reason why you don't just make the UITabViewController be the controller loaded by your app delegate? It seems that you have a level of indirection in your app that you may or may not need. It's probably better to simplify it now, and refactor later if you need something more complex.

Shaggy Frog
viewDidLoad can be called many times in the lifetime of a UIViewController. If -setView:nil is called on a NIB-based controller (which happens during the default -didReceiveMemoryWarning), the next time -view is called, -viewDidLoad will be called again. Misunderstanding this can lead to very hard-to-understand bugs.
Rob Napier
Edited to reflect this, thanks!
Shaggy Frog
I have been playing around with this indirection for a while. I'm trying to figure out what would be the "optimal" setup for my view controllers. The reason is that I wasn't sure what other views I may be loading up. Eventually I may want a loading screen, so the idea was I'd have my root view controller and it would decide if I need to show something else. If it needs to show a loading screen it would load it. The is my first real big app and I'm just trying to find a good structure. I was trying to avoid putting too much in the app delegate by putting all app logic in the view controllers
Brian
I also don't have a nib for my root view controller since I wanted it to be able to show other views. It basically looks at the state of the app and will show what is needed. Maybe I should re-examine my views and see if there is a need for this. I just don't want to work myself into a hole that I have to change later. Maybe this isn't the way to go. Any suggestions would be great.
Brian
+3  A: 

You should not implement both -viewDidLoad and -loadView; they are for different purposes. If you load a NIB, you should implement -viewDidLoad to perform any functions that need to be done after loading the NIB. Wiring up the tabbar is appropriate there if you haven't already done it in the NIB.

-loadView should be implemented if you do not use a NIB, and should construct the view.

-viewWillAppear is called immediately before you come onscreen. This is a good place to set up notification observations, update your data based on model classes that have changed since you were last on screen, and otherwise get your act together before the user sees you. You should not perform any animations here. You're not on the screen; you can't animate. I see a lot of animation glitches due to this mistake. It kind of works, but it looks weird.

-viewDidAppear is called after you come onscreen. This is where you do any entry animations (sliding up a modal, for instance; not that you should do that very often, but I was just looking at some code that did).

-viewWillDisappear is called right before you go offscreen. This is where you can do any leaving animations (including unselecting tableview cells and the like).

-viewDidDisappar is called after you're offscreen (and the animations have finished). Tear down any observations here, free up memory if possible, go to sleep as best you can.

I touch on setting up and tearing down observations here. I go into that in more depth in View controllers and notifications.

Rob Napier
Don't forget -viewDidUnload.
mahboudz
So if I'm not using a nib for my root view controller which loads a tab bar controller programmatically and then other root controllers into the tabs, I should do this in loadView? Thanks for the help.
Brian
Correct. If you're creating your view programmatically, you shouldn't use -viewDidLoad at all. @mahboudz: Yeah; I skipped over that one. -viewDidUnload is new in 3.0, and is the place to release any IBOutlets you're retaining (and you should be retaining your IBOutlets). In 2.x, we had to do this in setView: based on implementation details that Apple had to semi-document because you couldn't memory manage correctly without it. Luckily -viewDidUnload fixes all that. Hooray for 3.0.
Rob Napier