tags:

views:

1724

answers:

3

Is there a good overview of initWithNibName, awakeFromNib and viewDidLoad that lays out the best way to use each of these and describes exactly what each does? I find these very confusing. In the template that's generated with a View Controller, the comment about initWithNibName says: "The designated initializer. Override to perform setup that is required before the view is loaded." Except that this method never seems to be called (I'm using IB to set up the View Controller). So should I use awakeFromNib or viewDidLoad to initialize instead?

Thanks!

+4  A: 

If you're creating your views in IB, then you should use viewDidLoad. That will be called every time the view is initialized to be put up. You use initWithNibName: when you're creating your view in code. You shouldn't use awakeFromNib with views for the iPhone.

The reason that initWithNibName is not seeming to be called is that interface builder actually creates a real instance of your view controller and then serializes that view. So, when you create the view controller in IB (add it to your project, basically), IB calls initWithNibName, but unless you have overridden the default encodeWithCoder:, any transient variables that you've set up there will be gone when the view is loaded from the nib (deserialized). This is generally okay since you usually want to set up your view with information specific to your applications current, running context rather than pre-determined initializers.

Even if you are programmatically creating views and view controllers, however, you can still put all the intiialization in viewDidLoad. This is often better because if your view ends up getting cached (unloaded) and then brought back onto the screen, viewDidLoad can be called again while your initializer wouldn't necessarily be (e.g., you create a view programmatically and push it onto a navigation controller's stack--later the view has been covered up and a memory warning is issued so the nav controller "unloads" your view but doesn't release the object--when the view comes back (other views get popped off), the nav controller will call viewDidLoad again so you can re-initialize, but initWithNib will not be called again *note that this is a rare case and most people's applications will die horribly for other reasons at this point anyway, however).

Jason Coco
Jason - Thank you - this is really helpful! So follow up question: I am currently using awakeFromNib and viewWillAppear to do set up of my model (in awakeFromNib) and then use info from my model to set text in my view (in viewWillAppear). If I move the code in awakeFromNib to viewDidLoad, is it guaranteed to run before viewWillAppear? I need to make sure the setup code is running before viewWillAppear. I only want to set up the model once (obviously), so where's the best place to do that so that 1) it runs only once and 2) it runs before the viewWillAppear method? Thanks!
Elisabeth
Yes, it will run before viewWillAppear. It will also run every time the view is loaded (like after a memory warning), making this the place to do these kinds of things.
Jason Coco
Be careful putting one time init code in viewWillAppear because it gets called every time the view will become visible. So if you navigate or push another view controller, when they return to the parent view controller viewWillAppear is called again.
progrmr
+1  A: 

Sorry, not able (yet..) to comment. @Jason Coco : Why shouldn't we use awakeFromNib with the iPhone ? Do you think it's better to override initWithCoder ?

Unfalkster
A: 

I just finished doing some research on this topic so I thought I'd share a few of the things I learned.

1) There's nothing wrong with using awakeFromNib with views for the iPhone. See: http://developer.apple.com/iphone/library/documentation/uikit/reference/NSObject_UIKitAdditions/Introduction/Introduction.html

2) initWithCoder is not a good place to do initialization when the view is loaded from a NIB file because other items in the same NIB file may or may not have been initialized at that point. So an outlet might still be nil, for example. All items in the same NIB file are guaranteed to be initialized properly when awakeFromNib is called.

3) viewDidLoad is a good place to do setup work in the viewController.

So why would one want to use awakeFromNib in the view? One reason I can think of is if you have stuff you want to do after the view has been initialized and hooked up to the other objects in the NIB file, but you want to encapsulate it in the view only. This reduces linkage with the view controller.

justme