如何解决快速遍历不同变量类型的ForEach循环
我正在努力解决一个我认为(希望)有一个简单的解决方法的问题,您可能可以提供帮助。
我正在尝试对多个变量运行ForEach
循环。为了使事情简单,我只包含了两个变量,但还有更多变量,因此为什么我要使用ForEach
循环而不是为每个变量重复相同的代码。每个变量都基于不同的枚举。
预期结果
我想在我的代码中运行一个ForEach循环,该循环遍历变量数组并提取变量的描述和关联的rawValue。
变量
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)
}
}
实际结果
- 无法将'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)
}
}
}
错误:协议类型“ Any”的值不符合“ Hashable”;只有struct / enum / class类型可以符合协议
如果将[Any]
替换为[enum]
,则会出现以下错误:预期的元素类型
如果我用任何特定的枚举类型(例如[Any]
)将[EyeColor]
替换为无效的(并且可能也不适用于不同的枚举类型)。
解决方法
ForEach
有某些要求,它喜欢对Identifiable
个项目的集合进行迭代。考虑到这一点,让我们提供每个属性可以提供的struct Attribute
:
struct Attribute: Identifiable {
let name: String
let value: String
let id = UUID()
}
您可以将计算所得的var手动添加到提供此属性的每个枚举中,但这将是很多重复的代码。
相反,让我们注意,所有属性都提供了rawValue
和description
,而这正是初始化Attribute
所需的全部。
定义此协议:
protocol AttributeType {
var rawValue: String { get }
var description: String { get }
}
然后将此extension
创建为返回Attribute
的协议:
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,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
。如果属性是nil
或.notSet
,则为.witheld
。 -
.compactMap { $0 }
用于删除nil
值并为[Attribute]
创建ForEach
以便迭代。 - 由于
Attribute
是Identifiable
,因此它提供了id
,因此没有必要明确声明。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。