gpt4 book ai didi

swift - ForEach 循环遍历不同的变量类型 swift

转载 作者:行者123 更新时间:2023-12-04 13:11:51 24 4
gpt4 key购买 nike

我正在努力解决一个问题,我认为(希望)有一个简单的解决方法,您或许可以提供帮助。

我正在尝试对多个变量运行 ForEach 循环。为了简单起见,我只包含了两个变量,但还有更多变量,因此我想使用 ForEach 循环而不是为每个变量重复相同的代码。每个变量都基于不同的枚举。

预期结果

我想在我的代码中运行一个 ForEach 循环,循环遍历变量数组并提取变量的描述和关联的原始值。

变量

var profileEyeColor: EyeColor = EyeColor()
var profileHairColor: HairColor = HairColor()

枚举

enum EyeColor: String, CaseIterable {
case notSet
case amber
case blue
case brown
case gray
case green
case hazel
case other
case witheld

var description: String {
"Eye Color"
}

init() {
self = .notSet
}
}
enum HairColor: String, CaseIterable {
case notSet
case black
case blond
case brown
case auburn
case red
case gray
case white
case other
case witheld

var description: String {
"Hair Color"
}

init() {
self = .notSet
}
}

ForEach 循环

ForEach([profileEyeColor, profileHairColor], id: \.self) { item in
if item != .notSet && item != .witheld {
print(item.description)
print(item.rawValue)
}
}

实际结果

构建失败并且 xCode 错误包括:

  • 无法将“profileHairColor”类型的值转换为预期的元素类型“EyeColor”

替代尝试

我尝试使用 for 循环而不是 ForEach 来运行。我正在使用 SwiftUI,因此无法在正文中实现 for 循环。我也试过将它拆分成一个单独的函数,但在函数上出现错误。

func profileDetailsLoop(data: [Any]) -> View {
ForEach(data, id: \.self) { item in
if item != .notSet && item != .witheld {
HStack {
Text(item.description)
Text(item.rawValue)
}
}
}

错误:协议(protocol)类型“Any”的值不符合“Hashable”;只有结构/枚举/类类型可以符合协议(protocol)

如果我用 [enum] 替换 [Any] 那么我会收到以下错误:Expected element type

如果我将 [Any] 替换为任何特定的枚举类型,例如 [EyeColor] 将不起作用(并且大概也不会处理不同的枚举类型)。

最佳答案

ForEach 有一定的要求,它喜欢迭代 Identifiable 项的集合。考虑到这一点,让我们提供一个 struct Attribute,每个属性都可以提供:

struct Attribute: Identifiable {
let name: String
let value: String
let id = UUID()
}

您可以手动向提供此属性的每个枚举添加一个计算变量,但这会产生大量重复代码。

相反,让我们注意所有的属性都提供一个rawValue 和一个description,这就是初始化一个Attribute 真正需要的全部.

定义这个协议(protocol):

protocol AttributeType {
var rawValue: String { get }
var description: String { get }
}

然后为返回属性的协议(protocol)创建此扩展:

extension AttributeType {
var attribute: Attribute? {
guard self.isSet else { return nil }
return Attribute(name: self.description, value: self.rawValue)
}

var isSet: Bool { return !["notSet", "witheld"].contains(self.rawValue) }
}

最后,让您的所有枚举都采用AttributeType:

enum EyeColor: String, CaseIterable, AttributeType {
case notSet
case amber
...

var description: String {
"Eye Color"
}

init() {
self = .notSet
}
}


enum HairColor: String, CaseIterable, AttributeType {
case notSet
case black
...

var description: String {
"Hair Color"
}

init() {
self = .notSet
}
}

然后您可以通过访问 .attribute 属性为每个属性获取一个 Attribute

ForEach([profileEyeColor.attribute, profileHairColor.attribute].compactMap { $0 }) { attribute in
HStack {
Text(attribute.name)
Text(attribute.value)
}
}

为避免为数组中的每个 属性键入.attribute,您可以这样写:

ForEach([profileEyeColor as AttributeType, profileHairColor].compactMap { $0.attribute }) {

这将为长属性列表节省大量输入。

注意事项:

  • .attribute 返回一个可选 Attribute。如果属性为 .notSet.witheld,则为 nil
  • .compactMap { $0 } 用于删除 nil 值并为 ForEach 创建一个 [Attribute] > 迭代。
  • 由于 AttributeIdentifiable,它提供了 id,因此没有必要明确说明这一点。

关于swift - ForEach 循环遍历不同的变量类型 swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64303442/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com