Skip to main content

Working with View Controllers

1. Creating View Controllers

Method Description Code Example
init() Initializes a new view controller with default settings let viewController = UIViewController()
init(nibName:bundle:) Initializes a view controller with a specific nib file and bundle let viewController = UIViewController(nibName: "CustomView", bundle: nil)
init(coder:) Initializes a view controller from an archive (used with Storyboards)
required init?(coder: NSCoder) {
    super.init(coder: coder)
}
Note: When using Storyboards, the init?(coder:) initializer is called automatically.

2. Understanding View Lifecycle Methods

Method Description Notes
viewDidLoad() Called after the view controller's view is loaded into memory. Perfect for initial setup, such as configuring UI elements or setting up data sources.
viewWillAppear(_:) Called just before the view is added to the view hierarchy. Useful for preparing the view for display, such as animating in or updating content.
viewDidAppear(_:) Called after the view has been added to the view hierarchy and is visible. Good for starting animations or beginning tasks that require a visible view.
viewWillDisappear(_:) Called just before the view is removed from the view hierarchy. Useful for pausing animations or saving state before the view disappears.
viewDidDisappear(_:) Called after the view has been removed from the view hierarchy. Useful for cleaning up resources or stopping tasks that were started in viewWillAppear.
viewWillLayoutSubviews() Called just before the view's layout subviews are updated. Useful for making adjustments to subviews before they are laid out.
viewDidLayoutSubviews() Called after the view's layout subviews are updated. Useful for making adjustments to subviews after they have been laid out, such as adjusting frames or constraints.

Example: Using viewDidLoad to set up a view controller

class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "My View Controller"
        view.backgroundColor = .systemBackground
    }
}

3. Using viewDidLoad for Setup

viewDidLoad is called after the view controller's view has been loaded into memory. It's the ideal place to perform initial setup tasks that need the view to exist.

Method Description When It's Called
viewDidLoad() Called once when the view is first loaded After loadView and before the view appears

Example: Setting up UI in viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Set up the view hierarchy
    view.backgroundColor = .systemBackground
    
    // Configure UI elements
    let label = UILabel()
    label.text = "Hello, World!"
    label.textAlignment = .center
    label.translatesAutoresizingMaskIntoConstraints = false
    
    view.addSubview(label)
    
    NSLayoutConstraint.activate([
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
}
Note: Avoid heavy computation or network calls in viewDidLoad. Use viewWillAppear or viewDidAppear for such operations.

4. Using viewWillAppear and viewDidAppear

Method Description Usage
viewWillAppear(_: UIViewController method called before the view is added to the view hierarchy. Use for preparing the view before it appears (e.g., updating UI elements, starting animations).
viewDidAppear(_: UIViewController method called after the view has been added to the view hierarchy. Use for actions that should happen after the view is fully visible (e.g., starting timers, logging analytics).

Example: Using viewWillAppear and viewDidAppear

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("View will appear")
    // Update UI or prepare for appearance
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    print("View did appear")
    // Start timers or analytics
}
Note: Both methods are called every time the view appears, even if it's already in the view hierarchy.

5. Using viewWillDisappear and viewDidDisappear

Method Description Usage
viewWillDisappear(_ animated: Bool) Called when the view controller's view is about to be removed from the view hierarchy Use for cleaning up resources or stopping animations before the view disappears
viewDidDisappear(_ animated: Bool) Called after the view controller's view has been removed from the view hierarchy Use for final cleanup or logging after the view is no longer visible

Example: Managing view lifecycle

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // Stop animations or timers
    timer?.invalidate()
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    // Perform cleanup
    print("View disappeared")
}
Note: Both methods are called when the view is removed from the hierarchy, but viewWillDisappear is called before the view is actually removed.

6. Managing View Hierarchy

Method Description Notes
addChild(_:) Adds a child view controller to the current view controller Must be called before adding the child's view to the hierarchy
removeFromParent() Removes the view controller from its parent Must be called before removing the child's view
view.addSubview(_:) Adds a subview to the view controller's main view Used for direct view manipulation
viewWillDisappear(_:) Called when the view is about to be removed from the hierarchy Use for cleanup or state preservation

Example: Adding a Child View Controller

class ParentViewController: UIViewController {
    let childVC = ChildViewController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        addChild(childVC)
        view.addSubview(childVC.view)
        childVC.didMove(toParent: self)
    }
}

Example: Removing a Child View Controller

class ParentViewController: UIViewController {
    let childVC = ChildViewController()
    
    func removeChild() {
        childVC.willMove(toParent: nil)
        childVC.view.removeFromSuperview()
        childVC.removeFromParent()
    }
}
Note: Always call didMove(toParent:) after adding a child view controller, and willMove(toParent: nil) before removing it.

7. Working with Navigation Controllers

Property Description Notes
navigationController Reference to the navigation controller managing this view controller Read-only property
navigationBar Access to the navigation bar associated with this controller Can be customized for appearance and behavior

Example: Pushing a View Controller onto Navigation Stack

let newViewController = MyViewController()
navigationController?.pushViewController(newViewController, animated: true)

Example: Setting Navigation Bar Title

self.title = "My View Controller"

Example: Customizing Navigation Bar Appearance

UINavigationBar.appearance().backgroundColor = UIColor.blue
Note: Navigation controllers manage a stack of view controllers, allowing users to navigate back using the "back" button.
  • Initialize a UINavigationController with a root view controller
  • Push new view controllers onto the stack using pushViewController(_:animated:)
  • Pop view controllers using popViewController(animated:) or popToViewController(_:animated:)

8. Using Tab Bar Controllers

A UITabBarController is used to manage a set of view controllers, each associated with a tab in a tab bar. It provides a way to switch between different views or modes within an app.

Property Type Description
viewControllers [UIViewController] Array of view controllers to be displayed in the tab bar.
selectedIndex Int The index of the currently selected view controller.
tabBar UITabBar The tab bar managed by the controller.

Example: Setting up a Tab Bar Controller

import UIKit

class ViewControllerA: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Home"
        view.backgroundColor = .systemBlue
    }
}

class ViewControllerB: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Profile"
        view.backgroundColor = .systemGreen
    }
}

class TabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let vc1 = ViewControllerA()
        let vc2 = ViewControllerB()
        
        viewControllers = [vc1, vc2]
    }
}
Note: The UITabBarController manages the lifecycle of its view controllers, including their presentation and dismissal.

Key Features of Tab Bar Controllers

  • Each view controller is associated with a tab in the tab bar.
  • Supports customization of tab bar appearance and behavior.
  • Automatically handles switching between view controllers when a tab is selected.

9. Implementing Modal Presentations

Property Value Description
modalPresentationStyle .fullScreen, .pageSheet, .formSheet, .currentContext, .overFullScreen Defines how the view controller is presented modally
modalTransitionStyle .coverVertical, .flipHorizontal, .crossDissolve, .partialCurl Defines the transition animation when presenting modally

Example: Presenting a Modal View Controller

let modalViewController = MyModalViewController()
modalViewController.modalPresentationStyle = .formSheet
modalViewController.modalTransitionStyle = .coverVertical
present(modalViewController, animated: true)
Note: Use .formSheet for iPad and .fullScreen for iPhone to ensure proper presentation.

Example: Dismissing a Modal View Controller

@IBAction func dismissButtonTapped(_ sender: UIButton) {
    dismiss(animated: true)
}

10. Using Container View Controllers

A container view controller manages the layout and behavior of one or more child view controllers. It provides a structured way to organize and present multiple views within a single interface.

Property Description Usage
childViewControllers Array of child view controllers managed by the container. let children = self.childViewControllers
viewControllers Read-only array of view controllers in the container. let viewControllers = self.viewControllers
presentedViewController View controller currently presented modally. let modalVC = self.presentedViewController

Example: Adding a Child View Controller

class ParentViewController: UIViewController {
    let childVC = ChildViewController()

    override func viewDidLoad() {
        super.viewDidLoad()
        addChild(childVC)
        childVC.view.frame = view.bounds
        view.addSubview(childVC.view)
        childVC.didMove(toParent: self)
    }
}

Example: Removing a Child View Controller

class ParentViewController: UIViewController {
    let childVC = ChildViewController()

    func removeChild() {
        childVC.willMove(toParent: nil)
        childVC.view.removeFromSuperview()
        removeFromParent()
    }
}
Note: When adding or removing child view controllers, always call didMove(toParent:) or willMove(toParent:) respectively to notify the system of the change.

Container View Controller Types

  • UINavigationController: Manages a stack of view controllers.
  • UITabBarController: Displays one view controller at a time from a set of view controllers.
  • UISplitViewController: Displays two view controllers side-by-side on larger devices.
  • UIPageViewController: Allows navigation between pages of content using swipe gestures.

11. Understanding View Controller Transitions

Transition Type Description Usage Notes
Present Presents a view controller modally present(viewController, animated: true) Standard for showing new screens
Push Pushes a view controller onto a navigation stack navigationController?.pushViewController(viewController, animated: true) Used in navigation controllers
Pop Pops the current view controller off the navigation stack navigationController?.popViewController(animated: true) Reverses a push transition
Replace Replaces the current view controller in the navigation stack navigationController?.setViewControllers([newVC], animated: true) Useful for replacing entire stacks

Example: Presenting a Modal View Controller

let modalVC = MyModalViewController()
modalVC.modalPresentationStyle = .fullScreen
self.present(modalVC, animated: true)

Example: Pushing a View Controller

let detailVC = DetailViewController()
navigationController?.pushViewController(detailVC, animated: true)
Note: Transitions can be customized using UIViewControllerAnimatedTransitioning or UIViewControllerContextTransitioning.

Was this article helpful?