0

我尝试使用网格布局的这种解决方案。

我们希望在 Grid 中动态显示 Array Items,如果 Array.count Changed 出现 Index out of Range 错误并且应用程序崩溃。

如何解决这个问题?

var totalrows: Int{
    let t = Double(self.cards.count) / Double(self.cols)
    return Int(round(t))
}


var cols: Int{
    let col = self.verticalSizeClass == .compact ? 4 : 2
    return col
}



func colrow (col: Int , row: Int) -> Int{
    var colrow = 0
        colrow = (row * self.cols) + col
    return colrow
}






let cards = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"]



var body: some View {

        VStack{
            ForEach(0..<self.totalrows,id:\.self) { row in
                HStack {
                    ForEach(0..<self.cols,id:\.self) { column in
                        Text(self.cards[self.colrow(col: column, row: row)])
                    }


                }
               }
    }
}
4

3 回答 3

2

避免任何 indexOutOfBounds 的一种简单方法是在执行操作之前检查索引是否超出范围......

所以做这个改变:

ForEach(0..<self.cols,id:\.self) { column in
    let card = self.colrow(col: column, row: row)
    if (card < self.cards.count) {
        Text(self.cards[card])
    }
}

这将使您的最后一行可能未填充,但不应崩溃

于 2020-01-07T17:44:36.627 回答
0

cols返回 4 或 2 的方式,您将不得不countcards.

我会通过始终检查countofcards并在末尾添加一个空项目(如果还没有的话)来解决这个问题。

例子:

//only even numbers count
var cards = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"]

if (cards.count % 2) != 0 {
    cards.add("")
}
于 2020-01-07T17:41:23.360 回答
0

如果您添加自定义安全下标,您将能够使用 nil 合并将 index out boudns 数组元素替换为您喜欢的任何内容。

extension Array {
   subscript(guarded idx: Int) -> Element? {
        guard (startIndex..<endIndex).contains(idx) else { return nil }
        return self[idx]
    }
}

然后您可以像这样重写Text视图以显示无效索引的连字符并且没​​有崩溃。

//...
ForEach(0..<self.cols,id:\.self) { column in
                        Text(self.cards[guarded: self.colrow(col: column, row: row)] ?? "-")
                    }
//...
于 2020-06-06T10:39:02.417 回答