95

What is the difference between viewDidLoad and viewDidAppear? What kind of initialization or custom code goes into those functions?

e.g. presentModalViewController works only when present in viewDidAppear and not on viewDidLoad.

Cesare
  • 9,139
  • 16
  • 78
  • 130
user462455
  • 12,838
  • 18
  • 65
  • 96
  • See [UIViewController. viewDidLoad vs. viewWillAppear: What is the proper division of labor?](http://stackoverflow.com/questions/1579550/uiviewcontroller-viewdidload-vs-viewwillappear-what-is-the-proper-division-of) – Regan Sarwas Jul 22 '13 at 22:20

2 Answers2

160

viewDidLoad is called exactly once, when the view controller is first loaded into memory. This is where you want to instantiate any instance variables and build any views that live for the entire lifecycle of this view controller. However, the view is usually not yet visible at this point.

viewDidAppear is called when the view is actually visible, and can be called multiple times during the lifecycle of a View Controller (for instance, when a Modal View Controller is dismissed and the view becomes visible again). This is where you want to perform any layout actions or do any drawing in the UI - for example, presenting a modal view controller. However, anything you do here should be repeatable. It's best not to retain things here, or else you'll get memory leaks if you don't release them when the view disappears.

See: https://developer.apple.com/documentation/uikit/uiviewcontroller

Cœur
  • 37,241
  • 25
  • 195
  • 267
davidgoli
  • 2,436
  • 1
  • 16
  • 13
  • 18
    You and WrightsCS are absolutely right. But, not to split hairs, but while `viewDidLoad` is generally only called once and only once, there is one situation where it may be called again. Specifically, if you ever receive a `didReceiveMemoryWarning`, your non-visible views may be released (though the view controllers are untouched) and when you return back, `viewDidLoad` may be called for them again. – Rob Jun 29 '12 at 00:48
  • That's true, but in that case, any retained ivars will be released, so it's safe to reinitialize them... but if you retain an ivar in viewDidAppear and don't release it in viewDidDisappear, you're likely to get a memory leak if you're pushing other view controllers on top of the current one. – davidgoli Jun 29 '12 at 01:08
  • 1
    I'm not sure if I agree with the comment about view controller ivars always and automatically being released for you (the controller itself is _not_ released). I suspect we both could easily construct a viewDidLoad that would leak if it was re-invoked after a `didReceiveMemoryWarning`. But I agree that if you employ good practices when writing your `viewDidLoad`, you should be fine. My only point is that sloppy use of ivars and manual memory management can definitely result in leaks in `viewDidLoad`. People should be sensitive to the `didReceiveMemoryWarning` scenario and program accordingly. – Rob Jun 29 '12 at 01:46
  • 2
    Not to belabor the point, but less than 24 hours after this exchange, while answering [another question](http://stackoverflow.com/questions/11264963), I found an example of precisely the sort of `viewDidLoad` code that will leak upon `didReceiveMemoryWarning`. Sigh. – Rob Jun 30 '12 at 06:25
  • 1
    This answer directly contradicts this other one: http://stackoverflow.com/a/3411636/269753 I have been observing my viewDidLoad method being called more than just once, even when not receiving memory warnings at all. Anyone wants to clarify? – Ricardo Sanchez-Saez Apr 05 '13 at 10:48
  • 2
    I don't see that there's a contradiction. That question is about the relation between viewDidLoad and viewDidUnload, not viewDidAppear. – davidgoli Apr 26 '13 at 19:11
22

Simply put, you would want to create any controls or arrays in viewDidLoad, where as in viewDidAppear is where you would want to refresh those controls or arrays.

viewDidLoad is called once when the controller is created and viewDidAppear is called each time the view, well, DID appear. So say you have a modal view that you present, when that view is dismissed, viewDidAppear will be called, and viewDidLoad will not be called.

WrightsCS
  • 50,551
  • 22
  • 134
  • 186
  • 3
    First paragraph is a nicely put tip. But second paragraph is incorrect. `viewDidLoad` may be *called more than once*. If your view while not displayed (under a stack of other views) is unloaded by older versions of iOS in a low memory situation, then the view controller will automatically reload the view upon needing to be re-displayed on screen. In later versions of iOS you may choose to help reduce memory usage by doing what earlier iOS did for you: Unload offscreen views when `didReceiveMemoryWarning` message arrives, in which case the `viewDidLoad` will be called again. – Basil Bourque Nov 21 '13 at 20:57
  • 1
    @WrightsCS do you have any official apple doc that says that? "viewDidLoad is called once when the controller is created" Because I remember in the past viewDidLoad could be called several times under low memory scenarios. Thanks a lot. – Ricardo Dec 16 '15 at 15:09
  • https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/viewDidLoad – WrightsCS Dec 16 '15 at 19:47