UIKit — What It Is, Key Concepts, and Architecture

Author: IT Sectr Published: 2026-04-30 Reading time: 10 min

UIKit is a framework for building graphical interfaces in iOS and macOS applications. The toolkit includes UIView, UIViewController, control elements, and the Auto Layout system, enabling the creation of adaptive and interactive screens. According to Apple Developer Documentation (2025), UIKit contains over 200 classes for working with windows, views, animations, gestures, and text — it is the foundation of all iPhone and iPad applications.

Key Takeaways

  • UIKit is Apple's framework for building interfaces on iOS, iPadOS, and macOS with an imperative approach to view management.
  • UIView is the base class for all visual elements: buttons, text fields, images, and containers.
  • UIViewController manages the screen lifecycle: from view loading to memory deallocation.
  • Auto Layout describes element positioning through a system of constraints, adapting the interface to different screen sizes.
  • Delegates and dataSource are the key pattern for tables and collections, separating data from its display.

What is UIKit?

UIKit is a framework from Apple that provides classes for creating and managing user interfaces on iOS, iPadOS, and macOS (via Mac Catalyst). It works on top of Core Animation, Core Graphics, and Quartz Core, abstracting low-level rendering into high-level objects — buttons, labels, images, and containers. UIKit debuted with iPhone OS 1 in 2007 and remains the primary framework for iOS development alongside SwiftUI.

The framework follows an imperative approach: the developer creates instances of UIButton, UILabel, UIImageView classes, sets their properties (color, font, position), and adds them to the view hierarchy via addSubview. Every interface change is performed explicitly — no magic updates behind the scenes. This distinguishes UIKit from declarative frameworks like SwiftUI, where the state description automatically redraws the interface.

Core UIKit Classes

The framework includes several categories of classes. UIView is the base element from which all visual components inherit. UIWindow is the top-level container through which views are displayed on screen. UIViewController manages a set of views and responds to screen rotations, keyboard appearances, and system notifications. UIApplication is the entry point that processes touch events and button presses.

For text, UILabel (static text), UITextField (single-line input), and UITextView (multi-line input) are used. For buttons — UIButton, including system, custom, and SF Symbols iconography. For navigation — UINavigationController, UITabBarController, and UISplitViewController. In total, UIKit has over 200 public classes.

UIKit Architecture: Layers and View Hierarchy

UIKit architecture is built on layers: each layer is responsible for its own aspect of display. At the lowest level is Core Graphics — the rendering engine for paths, text, and images. Above it is Core Animation, which manages layer composition (CALayer) and animations between states. UIKit builds an object-oriented API on top of them: UIView, UIViewController, and UIResponder.

Every application has a view hierarchy — a tree whose root is the UIWindow. Below it is the root UIViewController, its view, and nested subviews inside. Touch events propagate along the responder chain: from the deepest nested view to its parents and up to UIApplication. If no object handles the touch, it is ignored.

UIView and CALayer

Each UIView contains a CALayer that handles pixel rendering on screen. The view manages touches and accessibility; the layer handles graphics — shadow, cornerRadius, border, transform. This separation allows heavy graphics to be offloaded to a separate thread (render server) without blocking the main thread. Apple recommends working directly with CALayer if more than 200 views are on screen — this reduces CPU load.

Responder Chain in Detail

The responder chain starts with the object that first receives a touch event. If it does not handle the event (the touchesBegan method is not overridden), the event moves to the next responder in the chain: next, superview, next responder, UIViewController, UIWindow, UIApplication, App Delegate. This allows global gestures and keyboard events to be intercepted at the scene level without adding a handler to every view.

UIViewController Lifecycle

Each UIViewController goes through a strictly defined sequence of events. The lifecycle includes phases: initialization, view loading, appearing on screen, layout update on rotation, hiding, leaving the screen, and memory deallocation. The developer overrides the corresponding methods to execute custom code at each stage.

swift
class ProfileViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        loadUserProfile()
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        clearCache()
    }
}

In viewDidLoad, the interface is configured — subviews are created, constraints are set, delegates are subscribed. In viewWillAppear, operations before display are performed: loading fresh data from the network, updating values. viewDidDisappear is the place to unsubscribe from notifications and clean up temporary data. Calling super is mandatory in all overrides, otherwise the event chain breaks.

Memory Management and viewDidUnload

In older iOS versions, the viewDidUnload method existed and was called when memory was low. Since iOS 6, the method has been removed — UIKit now automatically unloads views of controllers when they are not visible. The developer only needs to declare all view references as weak so that ARC can properly free memory upon receiving a system warning.

Transitions Between Controllers

UIKit supports two types of transitions: segue (via Storyboard) and programmatic navigation through UINavigationController. A programmatic transition looks like this: navigationController?.pushViewController(detailVC, animated: true). In this case, the detailVC lifecycle proceeds as usual — viewDidLoad is called once, viewWillAppear is called each time it appears.

Auto Layout and Adaptive Layout

Auto Layout is a positioning system based on mathematical relationships (constraints). Instead of hard-coded X and Y coordinates, the developer describes rules: “the button is to the right of the label with a 16pt offset” or “the view stretches across the screen width with 20pt margins on the left and right.” The system solves the resulting system of equations at runtime, adapting the interface to any screen size.

Constraints can be set in Interface Builder (via drag-and-drop) or programmatically in Swift. Each constraint is an instance of the NSLayoutConstraint class with parameters: firstItem, firstAttribute, relation, secondItem, secondAttribute, multiplier, constant. Constraints are activated via isActive = true or in bulk via NSLayoutConstraint.activate().

Safe Area and Layout Margins

With the introduction of iPhone X (2017), Apple introduced the Safe Area — the screen area free from the notch, rounded corners, and home bar indicator. Constraints should be attached to view.safeAreaLayoutGuide, not to view. Layout Margins add internal view padding, defaulting to 8pt or 16pt depending on context. Using safeAreaLayoutGuide ensures correct display on all iPhone and iPad generations.

Constraint Animation

Auto Layout supports animation by changing constraint constants. Simply update the constant of a constraint and call UIView.animate with layoutIfNeeded inside the animation block. The system smoothly recalculates the position of all views in the hierarchy. This technique is used for expandable blocks, adaptive keyboard panels, and screen orientation changes.

Working with Tables and Collections

UITableView and UICollectionView are two powerful UIKit tools for displaying lists and grids. UITableView is suitable for vertical single-column lists (chat, settings, news feed). UICollectionView is for grids, horizontal lists, carousels, and custom layouts (gallery, products, calendar). Both classes use the delegation pattern to separate data from appearance.

The data source is the UITableViewDataSource protocol with required methods numberOfRowsInSection and cellForRowAt. The UITableViewDelegate handles cell taps, row heights, and scroll events. The reuse identifier mechanism reuses cells that have scrolled off screen, which is critical for performance on large lists.

swift
class ContactsViewController: UITableViewController {

    private let contacts = ["Anna", "Boris", "Victor"]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self,
                           forCellReuseIdentifier: "cell")
    }

    override func tableView(_ tableView: UITableView,
                          numberOfRowsInSection section: Int) -> Int {
        return contacts.count
    }

    override func tableView(_ tableView: UITableView,
                          cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
                                                 for: indexPath)
        var content = cell.defaultContentConfiguration()
        content.text = contacts[indexPath.row]
        cell.contentConfiguration = content
        return cell
    }
}

The example shows a minimal controller for displaying an array of strings. The cell is configured via UIListContentConfiguration — a modern API (iOS 14+) that replaced the deprecated textLabel and detailTextLabel. Registering the cell class in viewDidLoad is mandatory, otherwise the application will crash with a runtime exception.

UICollectionView and Compositional Layout

Starting with iOS 13, Apple recommends UICollectionViewCompositionalLayout for building complex layouts. The developer describes the section, group, item, and their sizes declaratively — resulting in a grid with arbitrary geometry: a strip, 2x2 grid, carousel, or ornament. Compositional Layout has replaced the outdated UICollectionViewFlowLayout for all new projects. Combined with DiffableDataSource, updating a collection is reduced to a single apply(snapshot) call, and change animations are performed automatically.

Swift Code Examples

Below are two practical examples of using UIKit in real-world tasks: creating a custom view with shadow and rounded corners, and handling a swipe gesture to delete an item from a list.

swift
extension UIView {
    func applyCardStyle() {
        layer.cornerRadius = 12
        layer.shadowOpacity = 0.15
        layer.shadowRadius = 8
        layer.shadowOffset = CGSize(width: 0, height: 2)
        layer.masksToBounds = false
    }
}

@objc private func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
    guard let swipedView = gesture.view else { return }
    UIView.animate(withDuration: 0.3) {
        swipedView.alpha = 0
        swipedView.transform = CGAffineTransform(translationX: 300, y: 0)
    } completion: { _ in
        swipedView.removeFromSuperview()
    }
}

The applyCardStyle extension adds shadow and rounded corners to any view — useful for product cards, profiles, and notifications. The handleSwipe method with animation deletes an item when the user swipes right on it. The handler is added to the view via addGestureRecognizer with a UISwipeGestureRecognizer(direction: .right) configuration. Setting masksToBounds = false is important to prevent the shadow from being clipped by the view bounds.

For more complex interfaces, use UIStackView — a container that automatically distributes nested views horizontally or vertically. Stack View simplifies layout: no need to set constraints for each element, just one constraint for the stack itself.

Frequently Asked Questions

What is the difference between frame and bounds in UIView?

Frame is a rectangle in the superview's coordinates (position + size). Bounds is a rectangle in the view's own coordinates (always starts at 0,0). Frame changes on rotate and scale; bounds does not.

How to free memory from unused views?

UIKit automatically unloads views of hidden controllers. The developer only needs to declare view properties as weak var so that ARC can free memory upon a system warning.

Should I use Storyboard in 2026?

For new projects, Apple recommends SwiftUI. If the project uses UIKit — use XIB for individual screens or programmatic layout via SnapKit. Storyboard creates merge conflicts and slows down the build.

How to implement dark mode in UIKit?

Use UIColor with traitCollection support: UIColor { $0.userInterfaceStyle == .dark ? ... : ... }. Enable Dark Mode in Info.plist with the UIUserInterfaceStyle key.

How is UIStackView better than manual constraints?

UIStackView automatically calculates the positions and sizes of nested views based on alignment, distribution, and spacing. It reduces constraint code by 60–80% and simplifies adaptation to different screens.

Summary

  • UIKit is Apple's primary framework for building iOS, iPadOS, and macOS interfaces with an imperative approach.
  • UIView manages rendering and touches; its graphical part is handled by the CALayer layer, which runs on a separate thread.
  • UIViewController follows a strict lifecycle: from viewDidLoad to memory deallocation, with the ability to override each stage.
  • Auto Layout replaces fixed coordinates with a constraint system, adapting the interface to any screen size and orientation.
  • UITableView and UICollectionView with reuse identifiers ensure performance on large lists and support the modern Compositional Layout.
  • UIStackView simplifies layout of view sequences, reducing constraint code by 60–80%.
  • For new projects, Apple recommends SwiftUI, but UIKit remains relevant for supporting older iOS versions and complex custom interfaces.

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