Could you explain me the correct manner to manage the UIViewController
lifecycle?
In particular, I would like to know how to use Initialize
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
UPDATE: ViewDidUnload was deprecated in iOS 6, so updated the answer accordingly.
The UIViewController lifecycle is diagrammed here:
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.
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
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.
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.