Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
UIKit  ›  Lesson

The View Controller Lifecycle

ViewController Lifecycle 12 minUIKit calls viewDidLoad once when a view controller's view loads, and viewWillAppear, viewDidAppear, viewWillDisappear and viewDidDisappear each time it comes on or leaves the screen.

The View Controller Lifecycle

TrailLog's hike list is supposed to show a newly saved hike when you return to it. It doesn't — until you restart the app. The data was saved fine; the list just refreshed at the wrong moment in its lifecycle.

The rule

viewDidLoad happens once; the appear methods happen every time.

A view controller (UIViewController) manages one screen: it owns a root view, fills it with subviews, and responds to events. UIKit calls its lifecycle methods in a fixed order:

  1. viewDidLoad() — the view has been created and loaded into memory. Called once per controller. One-time setup: add subviews, configure the table, set the title.
  2. viewWillAppear(_:) — about to come on screen. Called every time it appears, including when the user comes back to it. Refresh data that may have changed.
  3. viewIsAppearing(_:) (newer iOS) and viewDidLayoutSubviews() — sizes are now known. Adjust anything that depends on final geometry.
  4. viewDidAppear(_:) — fully on screen. Start animations, begin tracking, log a screen view.
  5. viewWillDisappear(_:) — about to leave. Stop timers, save edits in progress.
  6. viewDidDisappear(_:) — gone from the screen. Release things only needed while visible.
final class HikeListViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "My Hikes"
        view.addSubview(tableView)            // once
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        hikes = store.allHikes()              // every time
        tableView.reloadData()
    }
}

Always call super first in these overrides; UIKit's own work depends on it.

Note what not to do in viewDidLoad: rely on final sizes. The view exists, but it may not have its on-screen size yet.

The shortcut

Ask: "Once, or every time it comes on screen?" Once → viewDidLoad. Every time → viewWillAppear. Needs final sizes → layout methods. Starts or stops something while visible → viewDidAppear / viewWillDisappear.

Fixing TrailLog's stale listStep 1 of 4
  1. Where was the reload?

    hikes = store.allHikes() sat in viewDidLoad, which ran once when the list was first created.

The trap is the reverse: adding subviews in viewWillAppear, which stacks a new copy of them every time the screen appears.

Drills

Answer fast — trust the rule.

quick drill

How many times is viewDidLoad called for one view controller instance?

quick drill

Where should TrailLog refresh its hike list so returning from another screen shows new data?

quick drill

Which comes first when a screen is shown for the first time?

quick drill

A GPS tracking timer should run only while the map screen is visible. Where do you stop it?

Remember

  • viewDidLoad happens once; viewWillAppear and viewDidAppear happen every time.
  • Shortcut: once or every time? Needs final sizes? Start or stop while visible?
  • Always call super; never add subviews in the appear methods.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainPlace the work

TrailLog's map screen must: add a map view, show the latest saved route each time it is shown, start a location-tracking animation once visible, and stop tracking when the user leaves. Assign each task to a lifecycle method and explain the rule you used.