Looking to understand the iOS UIViewController lifecycle
Asked Answered
P

11

329

Could you explain me the correct manner to manage the UIViewController lifecycle?

In particular, I would like to know how to use Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnload and Dispose methods in Mono Touch for a UIViewController class.

Pascale answered 6/4, 2011 at 7:39 Comment(1)
Is there some information or link for OSX ViewController and WindowController? Please share it.Eastertide
P
437

All these commands are called automatically at the appropriate times by iOS when you load/present/hide the view controller. It's important to note that these methods are attached to UIViewController and not to UIViews themselves. You won't get any of these features just using a UIView.

There's great documentation on Apple's site here. Putting in simply though:

  • ViewDidLoad - Called when you create the class and load from xib. Great for initial setup and one-time-only work.

  • ViewWillAppear - Called right before your view appears, good for hiding/showing fields or any operations that you want to happen every time before the view is visible. Because you might be going back and forth between views, this will be called every time your view is about to appear on the screen.

  • ViewDidAppear - Called after the view appears - great place to start an animations or the loading of external data from an API.

  • ViewWillDisappear/DidDisappear - Same idea as ViewWillAppear/ViewDidAppear.

  • ViewDidUnload/ViewDidDispose - In Objective-C, this is where you do your clean-up and release of stuff, but this is handled automatically so not much you really need to do here.

Phaih answered 6/4, 2011 at 17:17 Comment(8)
This text is slightly misleading, as the ViewDidLoad should not be used for one-time-only work. It might be called several times if the view is unloaded due to low memory and then loaded again.Brambly
ViewDidLoad is not actually called when you create/initialize the view controller. It is called the first time you do anything view related with the view controller's view. Like add it as a subview, set the frame, etc. It is also called of course when loading from a nib.Repeat
ViewDidAppear - Called after the view appears - great place to start an animations or the loading of external data from an API. Why is it a good place to start loading data? Why not viewDidLoad?Varick
what about loadView method, if it is called first time when a nib loaded in memory before viewDidLoad or not.Rutilant
@chakrit this is a good point - viewDidAppear is a great place to refresh data(if you need to). I disagree about KVO, because it can cause undesirable refreshes on the views that are never actually viewed by a user.Varick
will ViewDidLoad called when device orientation changes?Clavus
@astuter, No, ViewDidLoad will not be called when device orientation changes.Keeshakeeshond
I don't agree with ViewDidAppear part. I think ViewDidLoad is a good place if loading data only once, and ViewWillAppear is the place to refresh data.Fenestrated
H
418

UPDATE: ViewDidUnload was deprecated in iOS 6, so updated the answer accordingly.

The UIViewController lifecycle is diagrammed here:

A view controller's lifecycle, diagrammed

The advantage of using Xamarin Native/Mono Touch, is that it uses the native APIs, and so it follows the same ViewController lifecycle as you would find in Apple's Documentation.

Harbard answered 26/9, 2012 at 18:43 Comment(3)
Where do viewWillLayoutSubviews and viewDidLayoutSubviews go on this flowchart?Polanco
This diagram is inaccurate. viewDidUnload is deprecated since iOS6: #12509602Roede
This is indeed simply wrong. Another example of a simply wrong answer on SO, as the years pass. Computing is highly non-static.Lanugo
G
231

This is for latest iOS Versions(Modified with Xcode 9.3, Swift 4.1). Below are all the stages which makes the lifecycle of a UIViewController complete.

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Let me explain all those stages.

1. loadView

This event creates/loads the view that the controller manages. It can load from an associated nib file or an empty UIView if null was found. This makes it a good place to create your views in code programmatically.

This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly. Only override this method when you programmatically create views and assign the root view to the view property Don't call super method when you override loadView

2. loadViewIfNeeded

If incase the view of current viewController has not been set yet then this method will load the view but remember, this is only available in iOS >=9.0. So if you are supporting iOS <9.0 then don't expect it to come into the picture.

Loads the view controller's view if it has not already been set.

3. viewDidLoad

The viewDidLoad event is only called when the view is created and loaded into memory but the bounds for the view are not defined yet. This is a good place to initialise the objects that the view controller is going to use.

Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

4. viewWillAppear

This event notifies the viewController whenever the view appears on the screen. In this step the view has bounds that are defined but the orientation is not set.

Called when the view is about to made visible. Default does nothing.

5. viewWillLayoutSubviews

This is the first step in the lifecycle where the bounds are finalised. If you are not using constraints or Auto Layout you probably want to update the subviews here. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.

Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop.

6. viewDidLayoutSubviews

This event notifies the view controller that the subviews have been setup. It is a good place to make any changes to the subviews after they have been set. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.

Called just after the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop.

7. viewDidAppear

The viewDidAppear event fires after the view is presented on the screen. Which makes it a good place to get data from a backend service or database.

Called when the view has been fully transitioned onto the screen. Default does nothing

8. viewWillDisappear

The viewWillDisappear event fires when the view of presented viewController is about to disappear, dismiss, cover or hide behind other viewController. This is a good place where you can restrict your network calls, invalidate timer or release objects which is bound to that viewController.

Called when the view is dismissed, covered or otherwise hidden.

9. viewDidDisappear

This is the last step of the lifecycle that anyone can address as this event fires just after the view of presented viewController has been disappeared, dismissed, covered or hidden.

Called after the view was dismissed, covered or otherwise hidden. Default does nothing

Now as per Apple when you are implementing this methods you should remember to call super implementation of that specific method.

If you subclass UIViewController, you must call the super implementation of this method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, and specify nil for both of this methods arguments.) In the specified NIB, the File's Owner proxy should have its class set to your view controller subclass, with the view outlet connected to the main view. If you invoke this method with a nil nib name, then this class' -loadView method will attempt to load a NIB whose name is the same as your view controller's class. If no such NIB in fact exists then you must either call -setView: before -view is invoked, or override the -loadView method to set up your views programatically.

Hope this helped. Thanks.

UPDATE - As @ThomasW pointed inside comment viewWillLayoutSubviews and viewDidLayoutSubviews will also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.

UPDATE - As @Maria pointed inside comment, description of loadView was updated

Gesner answered 21/9, 2015 at 5:47 Comment(4)
viewWillLayoutSubviews and viewDidLayoutSubviews will also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.Neurilemma
There is a slight misleading in this answer: loadView() is always called, it just shouldn't be overridden when view for controller created in IB.Bridgetbridgetown
@Bridgetbridgetown Please go ahead and edit the answer if you think it can be improved. Thanks.Gesner
Default does nothing is wrong for viewWillAppear viewDidAppear viewDidDisappear. You must call super at some point.Jackinthebox
Y
51

iOS 10,11 (Swift 3.1,Swift 4.0)

According to UIViewController in UIKit developers,

1. loadView()

This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.

2. loadViewIfNeeded()

Loads the view controller's view if it has not already been set.

3. viewDidLoad()

Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

4. viewWillAppear(_ animated: Bool)

Called when the view is about to made visible. Default does nothing

5. viewWillLayoutSubviews()

Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.

6. viewDidLayoutSubviews()

Called just after the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.

7. viewDidAppear(_ animated: Bool)

Called when the view has been fully transitioned onto the screen. Default does nothing

8. viewWillDisappear(_ animated: Bool)

Called when the view is dismissed, covered or otherwise hidden. Default does nothing

9. viewDidDisappear(_ animated: Bool)

Called after the view was dismissed, covered or otherwise hidden. Default does nothing

10. viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

Called when the view is Transitioning.

11. willMove(toParentViewController parent: UIViewController?)

12. didMove(toParentViewController parent: UIViewController?)

These two methods are public for container subclasses to call when transitioning between child controllers. If they are overridden, the overrides should ensure to call the super.

The parent argument in both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new parent view controller.

13. didReceiveMemoryWarning()

Called when the parent application receives a memory warning. On iOS 6.0 it will no longer clear the view by default.

Yaakov answered 21/8, 2017 at 12:34 Comment(4)
It really really sux that stackoverflow won't purge all the wrong and incomplete answers from this entire thread. Your answer seems complete as far as method calls go, so I'm going to assume yours is correct and work with that.Untune
What is a nib as mentioned under loadView?Senega
@LogicsaurusRex I agree. In the same way that SO marks questions as duplicates or protected, I think it should be able to mark answers as outdated or obsoleteOzoniferous
Point 5 above is wrong. viewWillLayoutSubviews() is called before the ViewController's view object invokes its layoutSubviews() methodRadiolucent
O
28

As of iOS 6 and onward. The new diagram is as follows:

enter image description here

Orgasm answered 8/7, 2015 at 7:4 Comment(2)
Call that view "A". Consider a second view "B" that is appearing while "A" disappears. Is "B.viewWillAppear" before or after "A.viewDidDisappear"? And are there any situations where the order of those two changes?Keeshakeeshond
Seems like new view's (B) willApear will be called before the disAppears. For second question. Need some time to look into it.Orgasm
M
22

Let's concentrate on methods, which are responsible for the UIViewController's lifecycle:

  • Creation:

    - (void)init

    - (void)initWithNibName:

  • View creation:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • Handling of view state changing:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Memory warning handling:

    - (void)didReceiveMemoryWarning

  • Deallocation

    - (void)viewDidUnload

    - (void)dealloc

UIViewController's lifecycle diagram

For more information please take a look on UIViewController Class Reference.

Monoxide answered 12/5, 2016 at 9:43 Comment(0)
A
20

The methods viewWillLayoutSubviews and viewDidLayoutSubviews aren't mentioned in the diagrams, but these are called between viewWillAppear and viewDidAppear. They can be called multiple times.

Antimacassar answered 18/11, 2014 at 20:33 Comment(1)
They will also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.Neurilemma
A
16

Haider's answer is correct for pre-iOS 6. However, as of iOS 6 viewDidUnload and viewWillUnload are never called. The docs state: "Views are no longer purged under low-memory conditions and so this method is never called."

Allies answered 23/4, 2014 at 18:17 Comment(3)
I tried putting a breakpoint in ViewWillDisappear, ViewDidDisappear, Dispose. But none of them were getting invoked when I navigated with PresentViewController() method. What could be the reason ?Telfer
The link doesn't work ... So what does the OS do under low memory?Stedfast
Saves them to disk?Canthus
M
16

There's a lot of outdated and incomplete information here. For iOS 6 and newer only:

  1. loadView[a]
  2. viewDidLoad[a]
  3. viewWillAppear
  4. viewWillLayoutSubviews is the first time bounds are finalized
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews[b]
  8. * viewDidLayoutSubviews[b]

Footnotes:

(a) - If you manually nil out your view during didReceiveMemoryWarning, loadView and viewDidLoad will be called again. That is, by default loadView and viewDidLoad only gets called once per view controller instance.

(b) May be called an additional 0 or more times.

Mickiemickle answered 6/9, 2015 at 6:58 Comment(2)
viewWillLayoutSubviews and viewDidLayoutSubviews will also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.Neurilemma
@Neurilemma But not before viewDidLoad?Instauration
P
11

Explaining State Transitions in the official doc: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html

This image shows the valid state transitions between various view ‘will’ and ‘did’ callback methods

Valid State Transitions:


Taken from: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png

Phina answered 20/10, 2014 at 21:54 Comment(0)
I
0

As per Apple's doc — Start Developing iOS Apps (Swift) — Work with View Controllers — Understand the View Controller Lifecycle

viewDidLoad()—Called when the view controller’s content view (the top of its view hierarchy) is created and loaded from a storyboard. … Use this method to perform any additional setup required by your view controller.

viewWillAppear()—Called just before the view controller’s content view is added to the app’s view hierarchy. Use this method to trigger any operations that need to occur before the content view is presented onscreen

viewDidAppear()—Called just after the view controller’s content view has been added to the app’s view hierarchy. Use this method to trigger any operations that need to occur as soon as the view is presented onscreen, such as fetching data or showing an animation.

viewWillDisappear()—Called just before the view controller’s content view is removed from the app’s view hierarchy. Use this method to perform cleanup tasks like committing changes or resigning the first responder status.

viewDidDisappear()—Called just after the view controller’s content view has been removed from the app’s view hierarchy. Use this method to perform additional teardown activities.

Impala answered 4/3, 2018 at 0:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.