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
viewDidLoadhappens 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:
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.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.viewIsAppearing(_:)(newer iOS) andviewDidLayoutSubviews()— sizes are now known. Adjust anything that depends on final geometry.viewDidAppear(_:)— fully on screen. Start animations, begin tracking, log a screen view.viewWillDisappear(_:)— about to leave. Stop timers, save edits in progress.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.
Where was the reload?
hikes = store.allHikes()sat inviewDidLoad, 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.
How many times is viewDidLoad called for one view controller instance?
Where should TrailLog refresh its hike list so returning from another screen shows new data?
Which comes first when a screen is shown for the first time?
A GPS tracking timer should run only while the map screen is visible. Where do you stop it?
Remember
viewDidLoadhappens once;viewWillAppearandviewDidAppearhappen 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.
