How May I Test the Equivalency of Enumeration Cases with Associated Values in Swift 4

How may I test the equivalency of enumeration cases with associated values in Swift 4

The Swift proposal

  • SE-0185 Synthesizing Equatable and Hashable conformance

has been accepted and implemented in Swift 4.1 (Xcode 9.3):

... synthesize conformance to Equatable/Hashable if all of its members are Equatable/Hashable.

therefore it suffices to

... opt-in to automatic synthesis by declaring their type as Equatable or Hashable without implementing any of their requirements.

In your example – since String is Equatable – it will suffice to declare

enum AnEnumeration: Equatable {
case aSimpleCase
case anotherSimpleCase
case aMoreComplexCase(String)
}

and the compiler will synthesize a suitable == operator.

How to test equality of Swift enums with associated values

Swift 4.1+

As @jedwidz has helpfully pointed out, from Swift 4.1 (due to SE-0185, Swift also supports synthesizing Equatable and Hashable for enums with associated values.

So if you're on Swift 4.1 or newer, the following will automatically synthesize the necessary methods such that XCTAssert(t1 == t2) works. The key is to add the Equatable protocol to your enum.

enum SimpleToken: Equatable {
case Name(String)
case Number(Int)
}
let t1 = SimpleToken.Number(123)
let t2 = SimpleToken.Number(123)

Before Swift 4.1

As others have noted, Swift doesn't synthesize the necessary equality operators automatically. Let me propose a cleaner (IMHO) implementation, though:

enum SimpleToken: Equatable {
case Name(String)
case Number(Int)
}

public func ==(lhs: SimpleToken, rhs: SimpleToken) -> Bool {
switch (lhs, rhs) {
case let (.Name(a), .Name(b)),
let (.Number(a), .Number(b)):
return a == b
default:
return false
}
}

It's far from ideal — there's a lot of repetition — but at least you don't need to do nested switches with if-statements inside.

Swift Enum associated values conforming to single protocol

I've found the solution in case anyone will need this too.

enum ContentType {
case content1(Type1 & Refreshable)
case content2(Type2 & Refreshable)
case content3(someLabel: Type3 & Refreshable)

func refreshMe() {
let caseReflection = Mirror(reflecting: self).children.first!.value
(caseReflection as? Refreshable)?.refresh() //If associated type doesn't have label

let refreshable = Mirror(reflecting: caseReflection).children.first?.value as? Refreshable
refreshable?.refresh() //If associated type has label
}
}

swift enum get the associated value of multiple case with same parameters in single switch-case

You can put multiple enum values in the same case line, but you have to move the let into the ():

var value: Double {
switch self {
case .width(let value), .height(let value), .xxxxx1(let value):
return value
}
}

You might want to put each enum value on a separate line:

var value: Double {
switch self {
case .width(let value),
.height(let value),
.xxxxx1(let value):
return value
}
}

Unfortunately, that's about as elegant as it gets with enums with associated values. There's no way to get the associated value without explicitly listing the enums.

You can only combine values in the same line that have the same type of associated value, and all of the values have to bind to the same variable name. That way, in the code that follows, you know that the value is bound and what its type is no matter which enum pattern matched.

Accessing an Enumeration association value in Swift

The value is associated to an instance of the enumeration. Therefore, to access it without a switch, you need to make a getter and make it available explicitly. Something like below:

enum Number {
case int(Int)
case float(Float)

func get() -> NSNumber {
switch self {
case .int(let num):
return num
case .float(let num):
return num
}
}
}

var vInteger = Number.int(10)
var vFloat = Number.float(10.5)

println(vInteger.get())
println(vFloat.get())

Maybe in the future something like that may be automatically created or a shorter convenience could be added to the language.



Related Topics



Leave a reply



Submit