Tuesday, July 26, 2011

View Controller Life Cycle

View Controllers have a “lifecycle” from loading to unloading, and we have to override its delegate methods according to our requirement.

1.The life cycle starts with alloc and initialization:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)aBundle;
This is UIViewController’s designated initializer. The UIViewController tries to get its view from the specified .xib file called nibName.
If nibName is nil, it uses the name of the class as the nibName (MyViewController.xib).
The bundle allows you to specify one of a number of different .xib files (localization).
Passing nil for aBundle basically means “look in the Resources folder from Xcode.”
Initializing UIViewController with init is very common, it means nibName is nil & aBundle is nil.
Can I build a UIViewController’s view in code (i.e. w/o a .xib)? Yes. If no .xib is found using mechanism above, UIViewController will call - (void)loadView on itself. loadView’s implementation MUST set the view property in the UIViewController. Don’t implement loadView AND specify a .xib file (it’s undefined what this would mean).

2. viewDidLoad is called after the UIViewController is initialized.
- (void)viewDidLoad;
The viewDidLoad method is only called when the view is first loaded from the Nib file. If the view was already loaded and you push the view again it will not fire again. viewDidLoad is things you have to do once.Whenever I'm adding controls to a view that should appear together with the view, right away, I put it in the ViewDidLoad method. Basically this method is called whenever the view was loaded into memory. So for example, if my view is a form with 3 labels, I would add the labels here; the view will never exist without those forms.
3. Just before the view appears on screen, viewWillAppear is called.
- (void)viewWillAppear:(BOOL)animated;
Your view will probably only get “loaded” once, but it might appear and disappear a lot. So don’t put something in this method that really wants to be in viewDidLoad. Otherwise, you might be doing something over and over unnecessarily.
Use this to optimize performance by waiting until this method (i.e. just before view appears) to kick off an expensive operation (might have to put up a spinning “loading” icon though).
4. viewWillDisappear will be called when you will disappear off screen
- (void)viewWillDisappear:(BOOL)animated {
}
[superviewWillDisappear:animated]; //callthisinalltheviewWill/Didmethods // let’s be nice to the user and remember the scroll position they were at ... [selfrememberScrollPosition]; //we’llhavetoimplementthis // do some other clean up now that we’ve been removed from the screen
[self saveDataToPermanentStore];
// but be careful not to do anything time-consuming here, or app will be sluggish // maybe even kick off a thread to do what needs doing here
5. There are also “did” versions of both of these method:
- (void)viewDidAppear:(BOOL)animated; - (void)viewDidDisappear:(BOOL)animated;

6.  In low-memory situations, viewDidUnload is called. 
Be sure to release your outlets (or other data tied with the view and its subviews).

7. Now comes to device rotation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)anOrientation {
return (anOrientation == UIInterfaceOrientationPortrait) || (anOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
The default is to only allow UIInterfaceOrientationPortrait. This UIViewController’s view is allowed to flip around if the device is turned upside down. There is also UIInterfaceOrientationLandscapeLeft and Right. It is certainly nice to return YES from this method for as many as possible orientations.
But make sure that your view can draw itself “wide and not-tall” as well as “tall and not-wide” if you are going to return YES for the landscape orientations.

View Controller When rotation actually happens
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)anOrientation duration:(NSTimeInterval)seconds;
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)anOrientation; @property UIInterfaceOrientation interfaceOrientation;
The property will have the current orientation when each of the above is called. Stop doing anything expensive (e.g. an animation maybe?) in will and resume it in did.
The best way to handle rotations is to design your view to layout its subviews properly (i.e. set their frames) no matter what the aspect ratio of the view is.
Interface Builder can let you set “struts and springs” to help with layout flexibility. Or the UIView method layoutSubviews can be overridden to do this (outside this course’s scope).