SwiftUI ForEach使用\.self遇重复值报错,求低开销解决方法
SwiftUI ForEach遍历重复Color数组的ID冲突解决方法
问题背景
使用自定义资源Color数组遍历时,因重复Color实例导致id: \.self生成重复ID,控制台报错:
ForEach<Array, Color, _ShapeView<Rectangle, Color>>: the ID NamedColor(name: "InstrumentColor100", bundle: nil) occurs multiple times within the collection, this will give undefined results!
原代码:
let colors: [Color] = [Color("InstrumentColor100"),Color("InstrumentColor100"),Color("InstrumentColor101")] ForEach( colors, id: \.self) { color in Rectangle().fill(color) }
低开销解决方案
方案1:创建带唯一ID的中间容器类型
定义遵循Identifiable的结构体,自动生成UUID作为唯一标识:
struct ColorType: Identifiable { var id = UUID() var color: Color }
转换数组后遍历:
let colorItems = colors.map { ColorType(color: $0) } ForEach(colorItems) { item in Rectangle().fill(item.color) }
方案2:利用数组索引作为唯一ID
直接通过enumerated()获取元素索引,用索引作为ID,无需额外类型定义:
ForEach(Array(colors.enumerated()), id: \.offset) { _, color in Rectangle().fill(color) }
offset是数组元素的索引,天然唯一,完全满足ForEach的ID要求,开销最低。
方案3:给Color扩展全局唯一ID属性
如果需要在多处复用带唯一ID的Color,可扩展Color添加关联UUID:
extension Color { private static var idCache: [ObjectIdentifier: UUID] = [:] var uniqueId: UUID { let objId = ObjectIdentifier(self) if let cachedId = Color.idCache[objId] { return cachedId } else { let newId = UUID() Color.idCache[objId] = newId return newId } } }
使用时直接指定ID路径:
ForEach(colors, id: \.uniqueId) { color in Rectangle().fill(color) }
内容的提问来源于stack exchange,提问作者Symphonic eMotions
相关产品推荐
相关产品推荐

