The UIViewController lifecycle

viewDidLoad, viewWillAppear or viewDidLayoutSubviews?

Image for post
Image for post
Photo by Joseph Pearson on Unsplash

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

There is always much talk and thought about “what goes where” when thinking about and designing new iOS apps. You might well be familiar with the Application Life Cycle, but were you aware of the view controller’s similar journey?

Even if you are, I hope this article will help you out in understanding this essential part of UIKit.

Setting up a View Controller

A new instance of a UIViewController can be set up by simply creating a new Single View Project from Xcode. This quickly sets up the following:

Image for post
Image for post
Click for Gist

Which reveals that there are important thing to note. The ViewController is actually a subclass of UIViewController, which means that we have access to various methods which we can override to use.

The first of these is viewDidLoad() which most developers are familiar with, and I will go into detail about later in this article.

We are already given the like super.viewDidLoad() which is great, since we should be calling super for our overriden function.

If you can get this far you can already do great things like change the background of the view controller with a line like self.view.backgroundColor = .blue that is placed right in the viewDidLoad().

The lifecycle methods

viewDidLoad()

This is called after the view is loaded in to memory, and is commonly thought of as the first method that will be called.

You should not be doing layout in this method — it simply is too soon. You cannot assume that the bounds and frame that are given to you in viewDidLoad() are set and final (they might be correct, they might not be).

It is, of course, fine to configure views that will be calculated later. For example adding a subview that is placed with autolayout is absolutely fine, and here is an example of just that:

Image for post
Image for post
Click for Gist

This gives you the following rather dashing view.

Image for post
Image for post

Nice!

viewWillAppear(_:)

This is called just before the view controller is added to the view hierarchy and shown to the user. This means that the frame and bounds are all set, but we need to remember that these methods are called each and every time that the view controller is presented to he screen.

Similarly to viewDidLoad(_:) when overriding we should call super (that is super.viewWillAppear(_:))

viewDidAppear(_:)

Also known as the place to start animations, this is called when the user can see it. It’s not usually a good idea to flash things onto the screen at this point, as the user will see it!

As before, we should call super (that is super.viewDidAppear(_:))

viewWillLayoutSubviews()

The bounds are known and are guaranteed to be correct (as is the frame)! This can be called many times during the life of the view controller.

viewDidLayoutSubviews()

This is extremely important when the orientation of the device is changed. This can be called many times during the life of the view controller. Imagine we add a button at the bottom of the screen using the storyboard.

Image for post
Image for post

Now if we rotate the phone…where has the UIButton gone?

Image for post
Image for post

We can use viewDidLayoutSubviews() to reposition the button. We need to be aware that the function is called when the view is initially setup (that is, on the first instantiation of the view controller).

To carefully position the button we can use the frame of the view.

Image for post
Image for post
Click for Gist

Where this function is simply placed within the view controller.

viewWillDisappear(_:)

Called when the view is about to disappear from the user’s view. A good place to save user data and cancel network tasks.

As before, we should call super (that is super.viewWillDisapper(_:))

viewDidDisappear()

Called when the view controller has gone from the user’s view. The view has already disappeared, something like stopping music playing at this time would be a good choice.

As before, we should call super (that is super.viewDidDisapper(_:))

The order the lifecycle methods are called in

The functions were called in the following order:

viewDidLoad()
viewWillAppear(_:)
viewWillLayoutSubviews()
viewDidLayoutSubviews()
viewDidAppear(_:)

when the following code is run. You can check this out for yourself by either placing breakpoints in each method, or print logging (there’s a print(“will”) and print(“did”) there already). Here is the code (there is a link to the Gist just below the code if you want to copy — paste), which fully shows the black cube example shown above in this tutorial.

Image for post
Image for post
Click for Gist

Conclusion:

The little things in our projects make huge differences in both the user experience and how easy it is to maintain and add to our projects. Apple often refer to viewDidLoad(), viewDidAppear(), viewDidDisappear(), viewWillAppear(), viewWillDisappear() but much less is made of viewDidLayoutSubviews() yet to overcome layout problems, let us just say you will be using this method.

Any questions? Get in touch with me on Twitter or follow me here, it all helps these tutorials get made.

This guide should not only help you to use these functions, but even use them correctly. I hope this helps you.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store