I have an enum of associated values which I would like to make equatable for testing purposes, but do not know how this pattern would work with an enum case with more than one argument.
For example, summarised below I know the syntax for making heading equatable. How would this work for options, which contains multiple values of different types?
enum ViewModel { case heading(String) case options(id: String, title: String, enabled: Bool) } func ==(lhs: ViewModel, rhs: ViewModel) -> Bool { switch (lhs, rhs) { case (let .heading(lhsString), let .heading(rhsString)): return lhsString == rhsString case options... default: return false } }
I know Swift 4.1 can synthesize conformance for Equatable for us, but at present I am not able to update to this version.
We had to do this because Swift doesn't allow us to have both: raw values and associated values within the same enum. A Swift enum can either have raw values or associated values. Why is that? It's because of the definition of a raw value: A raw value is something that uniquely identifies a value of a particular type.
An enum without associated values has Equatable conformance even without the declaration. For an enum , all its associated values must conform to Equatable .
In Swift enum, we learned how to define a data type that has a fixed set of related values. However, sometimes we may want to attach additional information to enum values. These additional information attached to enum values are called associated values.
Each raw value for our enum case must be a unique string, character, or value of any integer or floating-point type. This means the value for the two case statements cannot be the same.
SE-0185 Synthesizing Equatable and Hashable conformance has been implemented in Swift 4.1, so that it suffices do declare conformance to the protocol (if all members are Equatable
):
enum ViewModel: Equatable { case heading(String) case options(id: String, title: String, enabled: Bool) }
For earlier Swift versions, a convenient way is to use that tuples can be compared with ==
.
You many also want to enclose the compatibility code in a Swift version check, so that the automatic synthesis is used once the project is updated to Swift 4.1:
enum ViewModel: Equatable { case heading(String) case options(id: String, title: String, enabled: Bool) #if swift(>=4.1) #else static func ==(lhs: ViewModel, rhs: ViewModel) -> Bool { switch (lhs, rhs) { case (let .heading(lhsString), let .heading(rhsString)): return lhsString == rhsString case (let .options(lhsId, lhsTitle, lhsEnabled), let .options(rhsId, rhsTitle, rhsEnabled)): return (lhsId, lhsTitle, lhsEnabled) == (rhsId, rhsTitle, rhsEnabled) default: return false } } #endif }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With