首页 > 解决方案 > 如何使用 [Int] 在 ForEach 中生成唯一 ID

问题描述

我正在使用 aForEach来构建基于 a 的多个视图array of integers。这array of integers可以包含重复值。另外,由于Int不是Identifiable我必须使用密钥路径。但是,在使用\.self时,由于重复值,我得到了不好的结果(矩形的颜色设置不正确)。

创建唯一标识符或密钥路径来解决此问题的最简单方法是什么?

@ViewBuilder
func stackFor(bar: Bar, scale: CGFloat) -> some View {
    //sample data
    let values = [4,4,5,6]
    var index = 0
    //create stack of view
    //==> since an Int is not identifiable I have to use keypath
    //    however \.self is not unique as we have 2x the value 4 in the values
    //    this leads bad results because there are duplica ids
    ForEach(values, id: \.self) { value in
        Rectangle()
            .fill(colorForStackedBar(index: index))
            .frame(height: heightFor(value: value, scale: scale) )
        Rectangle()
            .fill(Color.clear)
            .frame(height: 1 )
        //the let _ = ... is just a "hack" for being able to update the index in @ViewBuilder
        let _ = index = index + 1
    }
}

func colorForStackedBar(index: Int) -> Color {
    return barColors[safeIndex: index] ?? .red
}

func heightFor(value: Int, scale: CGFloat) -> CGFloat {
    let height = CGFloat(value) * scale
    //at least 1 point so to see __ on the bottom for zero (or missing) entries (as used on other apps)
    return max(1, height)
}

标签: swiftui

解决方案


我通过将 包装IntUnique:Identifiable结构中找到了解决方案。但是,我真的不认为这是最漂亮的解决方案。有没有更好的方法?

struct Unique: Identifiable {
    let value: Int
    let id = UUID()
}

@ViewBuilder
func stackFor(bar: Bar, scale: CGFloat) -> some View {
    //sample data
    let values = [4,4,5,6]
    var index = 0
    //generate a uuid for the whole array of values
    let uniques = values.map({Unique(value: $0)})
    ForEach(uniques) { unique in
        Rectangle()
            .fill(colorForStackedBar(index: index))
            .frame(height: heightFor(value: unique.value, scale: scale) )
        Rectangle()
            .fill(Color.clear)
            .frame(height: 1 )
        //the let _ = ... is just a "hack" for being able to update the index in @ViewBuilder
        let _ = index = index + 1
    }
}

推荐阅读