How to do if-else comparison for enumerations with arguments

Language : Swift2.3

For example, let me show you different types of transfers.

enum Normal { case one case two, three } enum NormalRaw: Int { case one case two, three } enum NormalArg { case one(Int) case two, three } 

Switch can be used for all three enumerations, for example:

 var normal: Normal = .one var normalRaw: NormalRaw = .one var normalArg: NormalArg = .one(1) switch normal { case .one: print("1") default: break } switch normalRaw { case .one: print(normalRaw.rawValue) default: break } switch normalArg { case .one(let value): print(value) default: break } 

In the if-else statement, although I can only compare Normal and NormalRaw , and the error message is displayed for NormalArg , so I can not run the code

The binary operator '==' cannot be applied to operands of type NormalArg and _

Here is a sample code:

 if normal == .two { // no issue .. do something } if normalRaw == .two { // no issue .. do something } if normalArg == .two { // error here (the above message) .. do something } if normalArg == .one(_) { // error here (the above message) .. do something } if normalArg == .three { // error here (the above message) .. do something } 

Any ideas? I really don't do anything with this code, I'm just wondering why we can't compare.

+5
source share
2 answers

The trick is that you don’t actually check with ==, but rather use the case keyword in conjunction with one = in your if statement. This is a bit contrasting intuitive at the beginning, but like if let , you get used to it pretty quickly:

 enum Normal { case one case two, three } enum NormalRaw: Int { case one = 1 case two, three } enum NormalArg { case one(Int) case two, three } let normalOne = Normal.one let normalRawOne = NormalRaw.one let normalArgOne = NormalArg.one(1) if case .one = normalOne { print("A normal one") //prints "A normal one" } if case .one = normalRawOne { print("A normal \(normalRawOne.rawValue)") //prints "A normal 1" } if case .one(let value) = normalArgOne { print("A normal \(value)") //prints "A normal 1" } 

The fact is that in Swift you only get a free, free enumeration equation if your enumeration uses a raw type or if you have no associated values ​​(try it, you cannot have both at the same time). However, Swift does not know how to compare cases with related values ​​- I mean, how could this be? Let's look at this example:

 Normal.one == .one //true Normal.one == .two //false NormalRaw.one == .one //true NormalRaw.one == .two //false NormalArg.one(1) == .one(1) //Well...? NormalArg.one(2) == .one(1) //Well...? NormalArg.one(1) == .two //Well...? 

Perhaps this explains why this cannot work out of the box:

 class Special { var name: String? var special: Special? } enum SpecialEnum { case one(Special) case two } var special1 = Special() special1.name = "Hello" var special2 = Special() special2.name = "World" special2.special = special1 SpecialEnum.one(special1) == SpecialEnum.one(special2) //Well...? 

So, if you want enumerations with related values, you will have to implement the Equatable protocol in your enumeration yourself:

 enum NormalArg: Equatable { case one(Int) case two static func ==(lhs: NormalArg, rhs: NormalArg) -> Bool { switch (lhs, rhs) { case (let .one(a1), let .one(a2)): return a1 == a2 case (.two,.two): return true default: return false } } } 
+19
source

The answer is Equableable Protocol .

Now let's see how it works.

Consider this enumeration, for example:

 enum Barcode { case upca(Int, Int) case qrCode(String) case none } 

If we check the equivalent operator == on an enumeration, it will not work.

 // Error: binary operator '==' cannot be applied to two Barcode operands Barcode.qrCode("code") == Barcode.qrCode("code") 

How to fix it using Equatable Protocol?

 extension Barcode: Equatable { } func ==(lhs: Barcode, rhs: Barcode) -> Bool { switch (lhs, rhs) { case (let .upca(codeA1, codeB1), let .upca(codeA2, codeB2)): return codeA1 == codeA2 && codeB1 == codeB2 case (let .qrCode(code1), let .qrCode(code2)): return code1 == code2 case (.None, .None): return true default: return false } } Barcode.qrCode("code") == Barcode.qrCode("code") // true Barcode.upca(1234, 1234) == Barcode.upca(4567, 7890) // false Barcode.none == Barcode.none // true 
+3
source

All Articles