iOS

⌘K
  1. Home
  2. Docs
  3. iOS
  4. UI Container Controllers
  5. UIViewController

UIViewController

What is UIViewController?

UIViewController is the base class for managing views in an iOS application. It provides lifecycle methods, navigation, and user interaction handling. Every screen in an iOS app is typically represented by a UIViewController.


1. Key Features of UIViewController

Manages the View Hierarchy – Handles UI elements on the screen.
Manages the View Lifecycle – Responds to events like loading, appearing, and disappearing.
Handles User Interaction – Processes button taps, gestures, and inputs.
Supports Navigation – Push, pop, and present other view controllers.
Manages Memory Efficiently – Releases resources when not in use.


2. UIViewController Lifecycle

A UIViewController goes through several states during its lifecycle:

Lifecycle Methods & Usage

MethodPurpose
viewDidLoad()Called when the view is loaded into memory. Used for setup.
viewWillAppear()Called before the view appears on the screen.
viewDidAppear()Called after the view appears. Used for animations.
viewWillDisappear()Called before the view disappears.
viewDidDisappear()Called after the view disappears.
viewWillLayoutSubviews()Called before layout changes.
viewDidLayoutSubviews()Called after layout changes.

Example: Lifecycle Methods in Action

import UIKit

class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print("View loaded into memory")
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("View will appear on screen")
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("View appeared on screen")
    }
}

3. Creating a UIViewController

3.1 Using Storyboard

  1. Open Main.storyboard.
  2. Drag a UIViewController from the Object Library.
  3. Set the Storyboard ID in the Identity Inspector.
  4. Create a new Swift file and subclass UIViewController.
  5. Connect the Storyboard UIViewController to this class.

3.2 Creating Programmatically

import UIKit

class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
    }
}

// Presenting the view controller in AppDelegate or SceneDelegate
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = MyViewController()
window.makeKeyAndVisible()

This programmatically creates a ViewController with a white background.


4. Navigating Between ViewControllers

4.1 Using Navigation Controller

A UINavigationController is used to push and pop view controllers.

let secondVC = SecondViewController()
navigationController?.pushViewController(secondVC, animated: true)

This pushes SecondViewController onto the navigation stack.

4.2 Presenting Modally

let modalVC = ModalViewController()
modalVC.modalPresentationStyle = .fullScreen
present(modalVC, animated: true, completion: nil)

This presents ModalViewController in fullscreen.

4.3 Dismissing a ViewController

dismiss(animated: true, completion: nil)

This dismisses the current ViewController.


5. Passing Data Between ViewControllers

5.1 Using Properties

class SecondViewController: UIViewController {
    var receivedText: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        print("Received data: \(receivedText)")
    }
}

// Passing data
let secondVC = SecondViewController()
secondVC.receivedText = "Hello from FirstVC!"
navigationController?.pushViewController(secondVC, animated: true)

5.2 Using Delegates (Recommended for Passing Data Back)

  1. Define a Protocol in SecondViewController
protocol SecondViewControllerDelegate: AnyObject {
    func didSendData(_ data: String)
}

class SecondViewController: UIViewController {
    weak var delegate: SecondViewControllerDelegate?
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        delegate?.didSendData("Data from SecondVC")
    }
}
  1. Conform to the Protocol in FirstViewController
class FirstViewController: UIViewController, SecondViewControllerDelegate {
    func didSendData(_ data: String) {
        print("Received: \(data)")
    }

    func navigateToSecondVC() {
        let secondVC = SecondViewController()
        secondVC.delegate = self
        navigationController?.pushViewController(secondVC, animated: true)
    }
}

This enables data passing back from SecondViewController to FirstViewController.


6. Adding UI Elements to UIViewController

6.1 Adding a Button Programmatically

let myButton = UIButton(type: .system)
myButton.setTitle("Click Me", for: .normal)
myButton.frame = CGRect(x: 100, y: 200, width: 150, height: 50)
myButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
view.addSubview(myButton)

@objc func buttonTapped() {
    print("Button Clicked!")
}

6.2 Adding a Label

let myLabel = UILabel()
myLabel.text = "Hello, World!"
myLabel.frame = CGRect(x: 50, y: 100, width: 200, height: 40)
view.addSubview(myLabel)

These examples show how to dynamically add UI elements to a ViewController.


7. Managing Memory Efficiently

To avoid memory leaks, use weak references and remove observers when necessary.

7.1 Removing Observers

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

7.2 Handling Retain Cycles

Use [weak self] in closures to prevent memory leaks:

myButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)

8. Handling Rotation and Size Changes

8.1 Detecting Orientation Changes

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    print("Device rotated, new size: \(size)")
}

8.2 Supporting Different Orientations

Add this to Info.plist:

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
</array>

This allows the app to support multiple screen orientations.


9. Summary

✔️ UIViewController manages screens in an iOS app.
✔️ Provides lifecycle methods to handle view loading and memory management.
✔️ Supports navigation and data passing between screens.
✔️ Can be customized programmatically or via Storyboard.
✔️ Uses delegates and closures for efficient communication between view controllers.

Would you like a specific ViewController feature implementation in your project? 🚀