viewDidLoad in iOS: What It Is, Purpose and Code Examples

Author: IT Sectr Published: 2026-03-05 Reading time: 8 min

viewDidLoad is the first method UIKit calls after loading the UIViewController’s View into memory. According to Apple Developer Documentation, this method is called exactly once during the entire lifetime of the controller. viewDidLoad is the primary place for initial interface setup, cell registration, and data initialization.

Key Takeaways

  • viewDidLoad is called once after loading the View into memory
  • super.viewDidLoad is required — without it, the Lifecycle breaks
  • In this method, you configure UI, register cells, and create data source
  • Not called again when returning to the screen — use viewWillAppear
  • Suitable for one-time operations and subscribing to permanent notifications

What is viewDidLoad

viewDidLoad is an instance method of UIViewController that UIKit calls immediately after the controller’s View has been loaded into memory. By this point, all IBOutlet properties are already connected to interface elements, but the View has not yet been added to the window hierarchy and is not visible to the user. The developer overrides this method to perform the initial screen configuration.

The method is part of the ViewController Lifecycle and follows immediately after loadView if the View is created programmatically, or after loading from Storyboard. In a typical project, viewDidLoad is the most frequently overridden method of UIViewController, as it provides a safe point for working with subviews that already exist and are ready for configuration.

An important detail: by the time viewDidLoad is called, the View’s dimensions do not yet correspond to the final ones — Auto Layout has not completed its passes, and the frame may differ from expectations. For calculations that depend on dimensions, use viewDidLayoutSubviews.

When viewDidLoad is called

The timing of the viewDidLoad call depends on how the controller is initialized. In most cases, UIKit calls this method automatically the first time the controller’s view property is accessed — this is called the lazy-loading mechanism of UIViewController.

On first screen appearance

When a NavigationController or TabBarController first displays your screen, UIKit checks whether the View is loaded. If not — loadView is called (or loading from Storyboard), after which viewDidLoad is immediately triggered. This is the standard scenario, and it happens once for each controller instance.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    print("View loaded — you can configure the interface")
    setupUI()
    configureTableView()
}

When returning to an existing screen

viewDidLoad is not called again when returning to the screen via the back button or dismiss. If your logic depends on the screen appearing again — place it in viewWillAppear. This is one of the most common conceptual mistakes: developers expect viewDidLoad to fire on every display, but UIKit calls it only once.

On forcedViewLoad

Sometimes developers forcibly access the controller’s view to trigger loading in advance: let _ = controller.view. This forces loadView and viewDidLoad to be called before the controller appears on screen. This technique is used when you need to prepare the View in advance for a smooth transition.

What to do in viewDidLoad

viewDidLoad is intended for one-time setup operations that do not depend on whether the screen is visible. Proper use of this method is the key to clean architecture and predictable controller behavior.

Configuring UI components

In viewDidLoad, you register nib files and classes for UITableView and UICollectionView, configure delegates, and set initial values for UI element properties. Since all IBOutlets are already connected by this point, you can safely access label.text, imageView.image, and other subview properties.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(
        CustomCell.self,
        forCellReuseIdentifier: CustomCell.identifier
    )
    title = "Main Screen"
}

Data initialization and subscriptions

Here you create a viewModel, initialize data source with arrays, and subscribe to notifications that should be active throughout the controller’s lifetime. For example, subscribing to UIApplication.willEnterForegroundNotification to update data when returning from the background is a good candidate for viewDidLoad. The viewModel in modern iOS architecture acts as a bridge between the controller and business logic, and initializing it in viewDidLoad ensures data readiness by the time the screen first appears.

Pay special attention to configuring the data source for tables and collections. If your table uses UIFetchedResultsController or NSFetchedResultsController with Core Data, initialize the fetch request and delegate in viewDidLoad. This guarantees that when the screen first appears, the table will already be populated with data without additional requests.

Navigation setup

In viewDidLoad, you configure NavigationBar buttons, set up large title, add a search controller, and set edit/done buttons. These elements rarely change when the screen is shown again, so initializing them here is optimal.

What not to do in viewDidLoad

Not all operations are appropriate in viewDidLoad. Some actions placed in this method lead to excessive memory consumption, incorrect behavior, or bugs when the screen is shown again.

Avoid starting network requests whose result only affects the UI. If the request completes before the screen appears, the user won’t see the result, and if it completes after — the data may be outdated. Initiate loading in viewDidLoad, but update the UI in viewWillAppear.

Do not perform operations in viewDidLoad that depend on the View’s size and position. At the time of the call, Auto Layout has not completed its passes, and the frame may not be final. For calculations, use viewDidLayoutSubviews or override updateViewConstraints.

Do not subscribe to notifications that are only relevant when the screen is visible. Keyboard notifications, content change notifications from child controllers — subscribe to them in viewWillAppear and unsubscribe in viewDidDisappear to avoid unnecessary calls and leaks.

Do not call methods that require a visible screen. For example, attempting to show a UIAlertController from viewDidLoad will result in an error because the controller’s View has not yet been added to the window hierarchy. Any UI operations that depend on the window or presentedViewController should only be performed after the screen appears.

Do not initialize heavy resources unnecessarily. If the screen is rarely shown or data is not displayed immediately, defer the creation of resource-intensive objects until they are actually needed. Lazy property initialization in Swift is a built-in mechanism for solving this problem: a property with the lazy modifier will be created only on first access, saving memory and speeding up screen loading.

Do not use viewDidLoad for operations that should be performed every time the screen appears. This is the most fundamental mistake: beginner developers often place data update logic in viewDidLoad and are surprised that when returning from another screen, the table does not reload. If an operation should repeat on every display — use viewWillAppear. If it should execute once per lifetime — use viewDidLoad. Remember this simple rule to avoid most problems with the UIViewController lifecycle.

Code examples with viewDidLoad

Let’s look at three practical examples demonstrating the correct use of viewDidLoad in real projects. Each example solves a specific screen configuration task.

Example 1: configuring a collection with custom cells

swift
override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.register(
        PhotoCell.self,
        forCellWithReuseIdentifier: PhotoCell.reuseId
    )
    collectionView.register(
        HeaderView.self,
        forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
        withReuseIdentifier: HeaderView.reuseId
    )
    viewModel.delegate = self
    viewModel.fetchInitialPage()
}

Example 2: setting up constraints programmatically

swift
override func viewDidLoad() {
    super.viewDidLoad()
    let label = UILabel()
    label.text = "Hello, world!"
    label.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(label)

    NSLayoutConstraint.activate([
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
}

Example 3: configuring empty state and loader

In viewDidLoad, you also configure elements displayed when there is no data: empty state, loader, placeholder. These components are created once and reused each time the screen appears. Hiding or showing these elements is managed in viewWillAppear depending on the current data.

swift
override func viewDidLoad() {
    super.viewDidLoad()
    emptyStateLabel = UILabel()
    emptyStateLabel.text = "No data"
    emptyStateLabel.textAlignment = .center
    emptyStateLabel.isHidden = true
    view.addSubview(emptyStateLabel)

    activityIndicator = UIActivityIndicatorView(style: .medium)
    activityIndicator.hidesWhenStopped = true
    view.addSubview(activityIndicator)
}

Example 4: subscribing to application notifications

swift
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleEnterForeground),
        name: UIApplication.willEnterForegroundNotification,
        object: nil
    )
}

@objc private func handleEnterForeground() {
    refreshContent()
}

Frequently Asked Questions

Can viewDidLoad be called more than once?

Under normal conditions, no — UIKit calls viewDidLoad once after loading the View into memory. If the controller is destroyed and created again, viewDidLoad will fire for the new instance.

Do I need to call super.viewDidLoad?

Yes, absolutely. Calling super.viewDidLoad ensures that UIKit performs the internal setup necessary for the Lifecycle to work correctly. Always call super first thing inside the method.

What is the difference between viewDidLoad and viewWillAppear?

viewDidLoad is called once when the View loads. viewWillAppear is called every time before the screen appears. The first is for one-time setup, the second is for updating data and state.

Can I perform heavy operations in viewDidLoad?

Heavy synchronous operations in viewDidLoad block the main thread and delay the screen appearance. Asynchronous loading is acceptable, but updating the UI upon completion must account for the possibility that the screen may already be hidden.

How to force call viewDidLoad?

You cannot call viewDidLoad directly — UIKit calls it. To force the View to load, access the controller.view property. This will trigger loadView and viewDidLoad automatically.

Summary

  • viewDidLoad is a one-time UIViewController setup method called after the View is loaded into memory
  • Called once during the controller’s lifetime on first access to the View
  • Suitable for cell registration, delegate configuration, viewModel initialization
  • Always call super.viewDidLoad for correct Lifecycle operation
  • Do not use viewDidLoad for operations that depend on View dimensions
  • For updating data on every appearance, use viewWillAppear
  • Subscribing to permanent notifications is appropriate, to temporary ones — in viewWillAppear

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also