Swift: Comparing Enums With Associated Values
Comparing enums in Swift is very straightforward – as long as they don’t have associated values. In this post, we will discuss what you can do in that case.
This post was originally published on 02/24/18 and updated on 02/12/23.
Let’s start with a simple case:
enum TestEnum {
case testA
case testB
}
let testEnum1 = TestEnum.testA
let testEnum2 = TestEnum.testB
let testEnum3 = TestEnum.testA
print(testEnum1 == testEnum2) //false
print(testEnum1 == testEnum3) //true
So in this example, we are defining an enum called TestEnum
, which has two cases. Then we are declaring two variables of this type and we compare them – they behave as expected and everything is working fine.
Enums With Associated Values
Now let’s look into the hard stuff. First, we add an associated value to one of the cases:
enum TestEnum {
case testA(Int)
case testB
}
let testEnum1 = TestEnum.testA(5)
As already explained in this post, you can use an enum with associated values to add some additional information. It can only be accessed within a switch statement though:
enum TestEnum {
case testA(Int)
case testB
}
let testEnum1 = TestEnum.testA(5)
switch testEnum1 {
case .testA(let a):
print("Case testA with associated value \(a)")
case .testB:
print("Case testB")
}
As expected, the output is
Case testA with associated value 5
Comparing Enums With Associated Values
So, now let’s try to compare two of them:
enum TestEnum {
case testA(Int)
case testB
}
let testEnum1 = TestEnum.testA(5)
let testEnum2 = TestEnum.testB
if testEnum1 == testEnum2 { //COMPILER ERROR!!!
print("equal")
}
In this case, we get a compiler error:
Binary operator '==' cannot be applied to two 'TestEnum' operands
And this makes sense because it’s not clear when they are equal. For example, are two testA
values equal if their associated values are equal? Or are two testA
values always equal? It depends on the circumstances and the meaning of the enum.
Subscribe to ThomasHanning.com
- iOS Dev & Swift Email Newsletter - Curated iOS development and Swift resources from around the web
- Exclusive posts for members only
- Be the first to know when new posts are released
- Write comments
Equatable protocol
But we can implemente our definition of ==
. For that, we implement the Equatable protocol:
enum TestEnum {
case testA(Int)
case testB
}
extension TestEnum: Equatable {
public static func ==(lhs: TestEnum, rhs:TestEnum) -> Bool {
switch lhs {
case .testA(let a):
switch rhs {
case .testA(let b):
return a == b
case .testB:
return false
}
case .testB:
switch rhs {
case .testB:
return true
case .testA:
return false
}
}
}
}
That’s a lot of code for a little bit of work, but it does the job! Now, two TestEnum
are equal, if one of the following two conditions is true:
- Both are
testB
cases. - Both are
testA
cases AND their associated values are equal.
Of course, it’s possible to write that code a little bit more elegant:
enum TestEnum {
case testA(Int)
case testB
}
extension TestEnum: Equatable {
public static func ==(lhs: TestEnum, rhs:TestEnum) -> Bool {
switch (lhs,rhs) {
case (.testB, .testB):
return true
case (.testA(let a), .testA(let b)):
return a == b
default:
return false
}
}
}
And now let’s test whether it’s working as expected:
let testEnum1 = TestEnum.testA(5)
let testEnum2 = TestEnum.testA(10)
let testEnum3 = TestEnum.testA(5)
let testEnum4 = TestEnum.testB
let testEnum5 = TestEnum.testB
print(testEnum1 == testEnum2) //false
print(testEnum1 == testEnum3) //true
print(testEnum1 == testEnum4) //false
print(testEnum4 == testEnum5) //true
It can also be implemented in another way, like this:
- Both are
testB
cases. - Both are
testA
cases
Then, the associated values don’t influence the equality:
extension TestEnum: Equatable {
public static func ==(lhs: TestEnum, rhs:TestEnum) -> Bool {
switch (lhs,rhs) {
case (.testB, .testB):
return true
case (.testA,.testA):
return true
default:
return false
}
}
}
let testEnum1 = TestEnum.testA(5)
let testEnum2 = TestEnum.testA(10)
let testEnum3 = TestEnum.testA(5)
let testEnum4 = TestEnum.testB
let testEnum5 = TestEnum.testB
print(testEnum1 == testEnum2)
print(testEnum1 == testEnum3)
print(testEnum1 == testEnum4)
print(testEnum4 == testEnum5)
As said before, it depends on the context.