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 enum
s with associated values. There's no way to get the associated value without explicitly listing the enum
s.
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
Swiftui: Can't Get the Transition of a Detailview to a Zstack in the Mainview to Work
Apply a Shadow on a Uiview That Have Same Corner Radius Than View
Swift Generics: Requiring Addition and Multiplication Abilities of a Type
Download File from Server Using Swift
How to Replicate Promisekit-Style Chained Async Flow Using Combine + Swift
How to Detect a Swiftui Touchdown Event with No Movement or Duration
Draw on a PDF Using Swift on MACos
Why Does Filter(_:)'s Predicate Get Called So Many Times When Evaluating It Lazily
Every Uialertcontroller Disappear Automatically Before User Responds - Since iOS 13
Manage Ifaddrs to Return MAC Addresses as Well in Swift
String Convert to Int and Replace Comma to Plus Sign
When Did 'Guard Let Foo = Foo' Become Legal
Swift 2: Expression Pattern of Type 'Bool' Cannot Match Values of Type 'Int'
How to Restrict Certain Characters in Uitextfield in Swift
Concatenate Two Audio Files in Swift and Play Them
Include Swiftui Views in Existing Uikit Application