Swift
Equatable Protocol
iOS Development
Swift Programming
Protocols

Swift Equatable Protocol

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Equatable gives Swift a standard way to answer whether two values should be considered equal. It is simple on the surface, but it matters everywhere from if statements to collection lookups, diffing logic, testing, and Hashable conformance.

What Equatable Requires

At its core, Equatable requires an implementation of ==.

swift
protocol Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool
}

Swift already provides this for many built-in types such as Int, String, and Bool, which is why comparisons like a == b work naturally.

For your own types, you can either let the compiler synthesize conformance or write the equality logic yourself.

Automatic Synthesis For Simple Types

For many structs and enums, Swift can generate the implementation automatically if all stored properties also conform to Equatable.

swift
1struct User: Equatable {
2    let id: Int
3    let name: String
4}
5
6let a = User(id: 1, name: "Ada")
7let b = User(id: 1, name: "Ada")
8let c = User(id: 2, name: "Grace")
9
10print(a == b) // true
11print(a == c) // false

This is usually the best starting point because the compiler-generated implementation is correct, concise, and easy to maintain.

Enums can also benefit from synthesis:

swift
1enum ConnectionState: Equatable {
2    case offline
3    case online(host: String)
4}
5
6print(ConnectionState.offline == .offline)
7print(ConnectionState.online(host: "a") == .online(host: "b"))

Associated values are included in the equality check automatically.

Manual Equality For Custom Semantics

Sometimes equality is not simply "all stored properties match." In those cases, implement == manually.

swift
1struct Article: Equatable {
2    let id: Int
3    let title: String
4    let lastViewedAt: Date
5
6    static func == (lhs: Article, rhs: Article) -> Bool {
7        return lhs.id == rhs.id
8    }
9}

Here, two Article values are considered equal if they represent the same logical entity, even if the title or last-viewed timestamp differs.

That is a legitimate design, but it should be intentional. Equality should reflect the meaning your program relies on, not just what happens to be convenient in one function.

Why Equatable Matters In Practice

Many standard library features depend on equality:

  • 'contains'
  • 'firstIndex(of:)'
  • testing assertions
  • diffing and state comparison

Example:

swift
1let users = [
2    User(id: 1, name: "Ada"),
3    User(id: 2, name: "Grace")
4]
5
6print(users.contains(User(id: 2, name: "Grace")))

Without Equatable, that kind of value-based lookup is not available.

Hashable also depends on consistent equality semantics. If two values compare equal, they must produce the same hash.

Be Careful With Reference Types

Classes can conform to Equatable too, but it is important to distinguish value equality from identity.

Identity asks:

  • Are these the exact same object in memory

Value equality asks:

  • Should these two instances be treated as equivalent by the program

For classes, you may sometimes want identity using ===, not ==.

swift
1final class Session: Equatable {
2    let id: Int
3
4    init(id: Int) {
5        self.id = id
6    }
7
8    static func == (lhs: Session, rhs: Session) -> Bool {
9        return lhs.id == rhs.id
10    }
11}

That makes two different instances equal if their IDs match, even though they are not the same object.

Keep Equality Predictable

Good equality should follow a few basic rules:

  • reflexive: a value equals itself
  • symmetric: if a == b, then b == a
  • transitive: if a == b and b == c, then a == c

You do not need to memorize the formal names to write Swift, but if your equality logic violates these ideas, collection behavior and tests become unreliable.

That is why "just compare one convenient field" can be dangerous if that field is not actually the type's identity.

Common Pitfalls

The most common mistake is writing custom equality when synthesized equality would be clearer and safer. If all stored properties define the identity, let the compiler do the work.

Another mistake is making equality too narrow. If two values compare equal but behave differently elsewhere in the program, bugs follow quickly.

People also confuse == with === on classes. == is value equality, while === checks whether two references point to the same instance.

Finally, if you later conform the type to Hashable, make sure the hashing logic matches the equality logic exactly.

Summary

  • 'Equatable defines value equality through ==.'
  • Swift can synthesize conformance for many structs and enums automatically.
  • Manual implementations are useful only when the type has custom equality semantics.
  • For classes, distinguish value equality from object identity.
  • Equality should be stable, predictable, and consistent with any future Hashable behavior.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.