Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How often is viewDidLoad called?

Tags:

When the user switches to another program and then back again., the original program's view will be replaced by a new view from another program. So when the user switches back to the original program, would viewDidLoad be called the second time ?

Am asking this because if this is the case, then the initialization code placed inside viewDidLoad would be executed every time the user switches the screen back and forth. And this could result in reseting views and loosing unfinished works of the user ...

like image 329
Stanley Avatar asked Feb 04 '12 00:02

Stanley


People also ask

Does viewDidLoad get called before viewWillAppear?

Always called after viewDidLoad (for obvious reasons, if you think about it), and just before the view appears on the screen to the user, viewWillAppear is called. This gives you a chance to do any last-minute view setup, kick off a network request (in another class, of course), or refresh the screen.

Is viewDidAppear called after viewDidLoad?

viewDidLoad is called after your view is loaded. It is called only once when view is initialized and pushed or presented. viewDidAppear is called once you see the loaded view on screen. It is called after view appeared.

What is called before viewDidLoad?

Yes viewdidload: is called before viewWillAppear:. and The apple developer guide says this method gets called after the view is loaded into memory means, The viewController in storyboard/XIB is loading into device memory.

What is the difference between viewDidLoad and viewDidAppear?

The difference between viewDidAppear and viewDidLoad is that viewDidAppear is called every time you land on the screen while viewDidLoad is only called once which is when the app loads.


2 Answers

Don't do view controller initialisation in viewDidLoad. This is a common mistake.

For stuff that should only happen once when the view controller is loaded, do it in the controller's init method, like this:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)bundleOrNil {     if ((self = [super initWithNibName:nibNameOrNil bundle:bundleOrNil]))     {         //do your initialisation here     }     return self; } 

The initWithNibName:bundle: method is called before the view is loaded from the nib, and is only called once in the lifespan of the view controller.

The controller's view can be loaded and unloaded multiple times during the lifespan of the controller and viewDidLoad will be called every time. It may be unloaded whenever it's not on screen, usually if memory is low.

If you do set stuff up in viewDidLoad (e.g. adding subviews programmatically) you should always unset them again in viewDidUnload.

Think of viewDidLoad and viewDidUnload as being like the init/dealloc for the view property of the view controller. For stuff that relates to the views, create and release it in those methods. For stuff that relates to the controller itself, create and release it in initWithNibName and dealloc.

UPDATE: On iOS 6 and later, viewDidUnload is never called any more (unless the view is explicitly set to nil in the code), and so viewDidLoad will typically only be called once in the life of a view controller. This makes the advice above less critical, but it's still best practice, and still necessary if you need to support iOS 5 and earlier.

UPDATE 2: If you are loading your view controller from a Storyboard (which is now the recommended practice) instead of creating it programmatically then initWithNibName:bundle: will not be called. Use initWithCoder: or awakeFromNib to initialize your controller instead.

like image 148
Nick Lockwood Avatar answered Sep 22 '22 05:09

Nick Lockwood


@Nick Lockwood provides excellent information, but there are a few more things to remember.

First, initWithNibName:bundle: is not called if the view controller is instantiated from a nib file or storyboard. In that case, initWithCoder: and awakeFromNib are called instead. This situation used to be somewhat uncommon on iOS, but with the addition of storyboards it is now much more common for view controllers to bypass initWithNibName:bundle:.

I recommend putting non-UI initialization code in a separate method (I call mine setup) and call it from both initWithNibName:bundle: and awakeFromNib. But I only do this if it's important that that initialization only run once. Otherwise I put it in viewWillAppear: to be as lazy-load as possible.

Second, you should not do anything that references self.view in init... or awakeFromNib. You should never reference self.view until viewDidLoad is called (otherwise you will force the nib file to be loaded sooner than it is needed). UI-related things should go in viewDidLoad if they're related to setting up the views, or viewWillAppear: if they're related to configuring the views (i.e. loading them with data).

So the way I usually set these things up:

@implementation   - (void)setup {   // Non-UI initialization goes here. It will only ever be called once. }  - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {   if ((self = [super initWithNibName:nibName bundle:bundle])) {     [self setup];   }    return self; }  - (void)awakeFromNib {   [self setup]; }  - (void)viewDidLoad {   // Any UI-related configuration goes here. It may be called multiple times,    // but each time it is called, `self.view` will be freshly loaded from the nib   // file. }  - (void)viewDidUnload {   [super viewDidUnload];   // Set all IBOutlets to `nil` here.   // Drop any lazy-load data that you didn't drop in viewWillDisappear: }  - (void)viewWillAppear:(BOOL)animated {   [super viewWillAppear:animated];   // Most data loading should go here to make sure the view matches the model   // every time it's put on the screen. This is also a good place to observe   // notifications and KVO, and to setup timers. }  - (void)viewWillDisappear:(BOOL)animated {   [super viewWillDisappear:animated];   // Unregister from notifications and KVO here (balancing viewWillAppear:).   // Stop timers.   // This is a good place to tidy things up, free memory, save things to   // the model, etc. }  - (void)dealloc {   // standard release stuff if non-ARC   [[NSNotificationCenter defaultCenter] removeObvserver:self]; // If you observed anything   // Stop timers.   // Don't unregister KVO here. Observe and remove KVO in viewWill(Dis)appear. }  @end 
like image 23
Rob Napier Avatar answered Sep 23 '22 05:09

Rob Napier