问题
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.
回答1:
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
}
回答2:
You can add something like below, check this link for more information. Return statement for options depend on your needs.
#if swift(>=4.1)
#else
func ==(lhs: ViewModel, rhs: ViewModel) -> Bool {
switch (lhs, rhs) {
case (let .heading(lhsString), let .heading(rhsString)):
return lhsString == rhsString
case (let .options(id1, title1, enabled1),let .options(id2, title2, enabled2)):
return id1 == id2 && title1 == title2 && enabled1 == enabled2
default:
return false
}
}
#endif
回答3:
Maybe not relevant for the OP but this might help others:
Remember that if you only want to compare an enum value against a fixed value, you can simply use pattern matching:
if case let ViewModel.heading(title) = enumValueToCompare {
// Do something with title
}
If you care about the associated value, you can add some conditions on it:
if case let ViewModel.heading(title) = enumValueToCompare, title == "SomeTitle" {
// Do something with title
}
来源:https://stackoverflow.com/questions/51300121/how-to-make-a-swift-enum-with-associated-values-equatable