如何使具有关联值的 Swift 枚举相等
How to make a Swift enum with associated values equatable
我有一个关联值的枚举,出于测试目的,我想使其相等,但不知道这种模式如何与具有多个参数的枚举一起工作。
例如,总结如下我知道使标题相等的语法。对于包含不同类型的多个值的选项,这将如何工作?
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
}
}
我知道Swift4.1可以为我们合成Equatable的一致性,但目前我无法更新到这个版本。
您可以添加如下内容,查看 this link 了解更多信息。
Return 选项声明取决于您的需要。
#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
SE-0185 Synthesizing Equatable and Hashable conformance 已在 Swift 4.1 中实现,因此 声明 符合协议就足够了(如果所有成员都是 Equatable
):
enum ViewModel: Equatable {
case heading(String)
case options(id: String, title: String, enabled: Bool)
}
对于早期的 Swift 版本,一个方便的方法是使用 元组 可以与 ==
.
进行比较
你们很多人还想在Swift版本检查中包含兼容性代码,以便在项目更新到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
}
可能与 OP 无关,但这可能对其他人有帮助:
请记住,如果您只想将枚举值 与固定值 进行比较,您可以简单地使用模式匹配:
if case let ViewModel.heading(title) = enumValueToCompare {
// Do something with title
}
如果你关心关联值,可以在上面加上一些条件:
if case let ViewModel.heading(title) = enumValueToCompare, title == "SomeTitle" {
// Do something with title
}
使用关联值的优雅方式(即使枚举是间接的):
首先你需要 value
属性:
indirect enum MyEnum {
var value: String? {
return String(describing: self).components(separatedBy: "(").first
}
case greeting(text: String)
case goodbye(bool: Bool)
case hey
case none
}
print(MyEnum.greeting(text: "Howdy").value)
// prints : greeting
现在您可以使用 value
来实现 Equatable
,如下所示:
indirect enum MyEnum: Equatable {
static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
lhs.value == rhs.value
}
var value: String? {
return String(describing: self).components(separatedBy: "(").first
}
case greeting(text: String)
case goodbye(bool: Bool)
case hey
case none
}
我有一个关联值的枚举,出于测试目的,我想使其相等,但不知道这种模式如何与具有多个参数的枚举一起工作。
例如,总结如下我知道使标题相等的语法。对于包含不同类型的多个值的选项,这将如何工作?
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
}
}
我知道Swift4.1可以为我们合成Equatable的一致性,但目前我无法更新到这个版本。
您可以添加如下内容,查看 this link 了解更多信息。 Return 选项声明取决于您的需要。
#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
SE-0185 Synthesizing Equatable and Hashable conformance 已在 Swift 4.1 中实现,因此 声明 符合协议就足够了(如果所有成员都是 Equatable
):
enum ViewModel: Equatable {
case heading(String)
case options(id: String, title: String, enabled: Bool)
}
对于早期的 Swift 版本,一个方便的方法是使用 元组 可以与 ==
.
你们很多人还想在Swift版本检查中包含兼容性代码,以便在项目更新到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
}
可能与 OP 无关,但这可能对其他人有帮助:
请记住,如果您只想将枚举值 与固定值 进行比较,您可以简单地使用模式匹配:
if case let ViewModel.heading(title) = enumValueToCompare {
// Do something with title
}
如果你关心关联值,可以在上面加上一些条件:
if case let ViewModel.heading(title) = enumValueToCompare, title == "SomeTitle" {
// Do something with title
}
使用关联值的优雅方式(即使枚举是间接的):
首先你需要 value
属性:
indirect enum MyEnum {
var value: String? {
return String(describing: self).components(separatedBy: "(").first
}
case greeting(text: String)
case goodbye(bool: Bool)
case hey
case none
}
print(MyEnum.greeting(text: "Howdy").value)
// prints : greeting
现在您可以使用 value
来实现 Equatable
,如下所示:
indirect enum MyEnum: Equatable {
static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
lhs.value == rhs.value
}
var value: String? {
return String(describing: self).components(separatedBy: "(").first
}
case greeting(text: String)
case goodbye(bool: Bool)
case hey
case none
}