Swift
Delegates
iOS Development
Programming
Swift Language

Delegates in swift?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Delegation is one of the most common communication patterns in Swift, especially in UIKit and AppKit code. It lets one object announce events or ask for decisions without tightly coupling itself to a specific implementation.

What a Delegate Actually Does

A delegate is another object that receives callbacks from the object doing the work. In Swift, the pattern is usually built with a protocol, a delegate property, and one or more methods that describe the messages being sent.

This design keeps responsibilities separate. A reusable component can focus on its own job, while another object decides how to respond to events. A table view, for example, knows when a row was selected, but it delegates the response to another object.

The pattern has three recurring pieces:

  • a protocol that defines the callback methods
  • a delegate property, usually marked weak
  • a class that adopts the protocol and handles the event

Building a Simple Delegate in Swift

The example below works in a Swift playground or command-line project. Counter performs a task, and Logger reacts whenever the value changes.

swift
1import Foundation
2
3protocol CounterDelegate: AnyObject {
4    func counter(_ counter: Counter, didReach value: Int)
5}
6
7final class Counter {
8    weak var delegate: CounterDelegate?
9    private(set) var value = 0
10
11    func increment() {
12        value += 1
13        delegate?.counter(self, didReach: value)
14    }
15}
16
17final class Logger: CounterDelegate {
18    func counter(_ counter: Counter, didReach value: Int) {
19        print("Counter is now \(value)")
20    }
21}
22
23let counter = Counter()
24let logger = Logger()
25
26counter.delegate = logger
27counter.increment()
28counter.increment()

A few details are worth noticing. The protocol inherits from AnyObject, which allows the delegate reference to be weak. That matters because delegates are often long-lived UI controllers, and a strong reference can create a retain cycle.

The Counter class also does not know anything about Logger. It only knows that the delegate conforms to CounterDelegate. That decoupling is the main reason delegation stays useful even in codebases that also use closures, Combine, or async streams.

When Delegates Are a Good Fit

Delegates work well when one object owns a process and another object needs structured callbacks over time. They are especially useful when:

  • multiple related callbacks belong together
  • the sender should remain reusable and framework-like
  • the receiver needs context from the sender
  • communication is one-to-one rather than broadcast

That is why Apple uses delegates heavily in views, controllers, networking APIs, and data pickers. A single delegate can answer several questions and react to several events without the sender knowing app-specific details.

Closures can be a better fit for one-off callbacks. Delegates are usually better when the communication is ongoing and has a small protocol-shaped surface.

Common Pitfalls

  • Forgetting weak on the delegate property. If both objects strongly reference each other, neither will be released.
  • Omitting AnyObject from the protocol when you intend to use a weak reference. Only class-bound protocols can be referenced weakly.
  • Letting the delegate disappear too early. If the delegate object is deallocated, callbacks stop because the weak reference becomes nil.
  • Putting too much app logic in the sender. The sender should report events, not become tightly coupled to one screen or workflow.
  • Using delegates for simple one-time results where a closure would be clearer and easier to read.

Summary

  • A delegate is an object that receives callbacks from another object through a protocol.
  • In Swift, delegation is usually implemented with a protocol plus a weak delegate property.
  • The pattern helps keep reusable components decoupled from app-specific behavior.
  • Add AnyObject to delegate protocols when the delegate should be held weakly.
  • Use delegates for ongoing structured callbacks, and prefer closures for simpler one-off responses.

Course illustration
Course illustration

All Rights Reserved.