UIViewController viewDidLoad vs. viewWillAppear: What is the proper division of labor?
Asked Answered
P

4

167

I have always been a bit unclear on the type of tasks that should be assigned to viewDidLoad vs. viewWillAppear: in a UIViewController subclass.

e.g. I am doing an app where I have a UIViewController subclass hitting a server, getting data, feeding it to a view and then displaying that view. What are the pros and cons of doing this in viewDidLoad vs. viewWillAppear?

Proselyte answered 16/10, 2009 at 18:9 Comment(0)
S
253

viewDidLoad is things you have to do once. viewWillAppear gets called every time the view appears. You should do things that you only have to do once in viewDidLoad - like setting your UILabel texts. However, you may want to modify a specific part of the view every time the user gets to view it, e.g. the iPod application scrolls the lyrics back to the top every time you go to the "Now Playing" view.

However, when you are loading things from a server, you also have to think about latency. If you pack all of your network communication into viewDidLoad or viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freeze of your app. It may be good idea to first show the user an unpopulated view with an activity indicator of some sort. When you are done with your networking, which may take a second or two (or may even fail - who knows?), you can populate the view with your data. Good examples on how this could be done can be seen in various twitter clients. For example, when you view the author detail page in Twitterrific, the view only says "Loading..." until the network queries have completed.

Snag answered 16/10, 2009 at 18:28 Comment(9)
So, regarding viewWillAppear potentially being called repeatedly. Would that method fire if, for example, the viewcontrollers view became visible after having been hidden (I mean occluded here, not the hidden method on UIView). In what scenerio would viewWillAppear be called without being preceded by a call to viewDidLoad?Proselyte
viewDidLoad ONLY gets called when the view is constructed - so for example after a view controller initFromNibNamed call when the view is accessed. viewWillAppear is called anytime your view controller was not in view but comes into view - so when your view controller is pushed, viewWillAppear is called. If you push another subview from there, and the user returns, viewWillAppear is called again.Crumple
Thanks Kendall. Yah, a few strategically placed NSLogs got me sorted. viewWillAppear/viewWillDissappear fire on viewcontroller push/pops.Proselyte
Note that viewDidLoad will ALSO get called if the view is hidden and then unloaded for memory-related reasons, then reappears. What you can count on: viewDidLoad will be called AT LEAST ONCE when the view is first created and POSSIBLY more times when the view reappears after being hidden. viewWillAppear will ALWAYS be called when the view is about to appear onscreen.Languishing
Can someone please comment further on these two related questions: (1) Sometimes, not always, frame values for controls (i.e., origin and size) are zero in viewDidLoad, and sometimes not --Why? (2) In Apple's template for a splitViewController's detailView (iPad), there's a configureView method -- what should go in there relative to viewDidLoad and ViewWillAppear?Charcuterie
... continuing #2... Doing anything with frames or subviews in configureView will fire viewDidLoad (if it hasn't been called already), causing configureView to be entered again before the first call exits. Confusing.Charcuterie
viewWillAppear is not necessarily called when a view becomes unoccluded. E.g., when you have a UIImageView completely occluding the entire screen, as a subview of the tab bar, and then remove this UIImageView, the viewWillAppear method of the top view controller will not be called.Babette
@Charcuterie is correct, there is an issue with using viewDidLoad for positioning other frames, I see weird behaviors when working with viewDidLoad, for example UICollectionView cells were created with a frame that is all zeros... I couldn't find a place for one-time init and positioning of frames...Auxochrome
There is ALSO a bit of funkiness when using embedded views in containers (this is annoying) - prepareForSegue will get called BEFORE viewWillAppear to set up the containers. Meaning if you have some initialization for the embedded view BEFORE your view appears, it needs to be in the prepareForSegue, NOT in viewWillAppear.Pepperandsalt
A
13

It's important to note that using viewDidLoad for positioning is a bit risky and should be avoided since the bounds are not set. this may cause unexpected results (I had a variety of issues...)

This post describes quite well the different methods and what happens in each of them.

currently for one-time init and positioning I'm thinking of using viewDidAppear with a flag, if anyone has any other recommendation please let me know.

Auxochrome answered 26/6, 2014 at 17:49 Comment(2)
agree with this : "... should be avoided since the bounds are not set ..."Germanophile
great link. Everyone must see itTruant
L
12

Initially used only ViewDidLoad with tableView. On testing with loss of Wifi, by setting device to airplane mode, realized that the table did not refresh with return of Wifi. In fact, there appears to be no way to refresh tableView on the device even by hitting the home button with background mode set to YES in -Info.plist.

My solution:

-(void) viewWillAppear: (BOOL) animated { [self.tableView reloadData];}
Luthuli answered 29/11, 2012 at 20:52 Comment(0)
T
5

Depends, Do you need the data to be loaded each time you open the view? or only once?

enter image description here

  • Red : They don't require to change every time. Once they are loaded they stay as how they were.
  • Purple: They need to change over time or after you load each time. You don't want to see the same 3 suggested users to follow, it needs to be reloaded every time you come back to the screen. Their photos may get updated... you don't want to see a photo from 5 years ago...

viewDidLoad: Whatever processing you have that needs to be done once.
viewWilLAppear: Whatever processing that needs to change every time the page is loaded.

Labels, icons, button titles or most dataInputedByDeveloper usually don't change. Names, photos, links, button status, lists (input Arrays for your tableViews or collectionView) or most dataInputedByUser usually do change.

Truant answered 8/9, 2016 at 16:17 Comment(2)
The purple would be called in the viewDidAppear not the viewWillAppearGolgi
@AlexKornhauser what do you mean it would be called? I'm saying in your viewWillAppear you can query and check the latests tweets. viewDidAppear is too late for thatTruant

© 2022 - 2024 — McMap. All rights reserved.