Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a Swift enum with associated values equatable

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.

like image 468
Stamp Avatar asked Jul 12 '18 07:07

Stamp


People also ask

Why Swift enums with associated values Cannot have a raw value?

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.

Is enum Equatable?

An enum without associated values has Equatable conformance even without the declaration. For an enum , all its associated values must conform to Equatable .

What is associated values in enum Swift?

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.

What is raw value or associated value in enum in Swift?

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.


1 Answers

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 } 
like image 81
Martin R Avatar answered Sep 21 '22 12:09

Martin R