SwiftUI + ForEach 在使用新维度重绘矩阵时遇到“索引超出范围”

问题描述 投票:0回答:1

我使用 SwiftUI 的 ForEach 从视图模型中的矩阵绘制一个网格,该网格包含相同数量的行和列。我希望能够点击一个按钮并切换到一个新的矩阵,该矩阵具有不同长度的行和列(但仍然是方形网格)。 当我点击按钮并切换矩阵时,ForEach 会超出范围,同时尝试使用前一个网格的尺寸绘制较小的网格。

矩阵包含

RewardCell
元素,我已符合
Identifiable
Hashable
:

struct RewardCell: Identifiable {
    var isVisible: Bool = false
    let id: String = UUID().uuidString
    let coord: CGPoint
}

extension RewardCell: Hashable {
    func hash(into hasher: inout Hasher) {
        hasher.combine(isVisible)
    }
    
    static func == (lhs: RewardCell, rhs: RewardCell) -> Bool {
        lhs.coord == rhs.coord
    }
}

ForEach 强力通过矩阵,同时绘制它的视图,如下所示......

Grid(horizontalSpacing: 0, verticalSpacing: 0) {
    ForEach(rewards.grid, id: \.self) { row in
        GridRow {
            ForEach(row, id: \.self) { element in
                RewardGridCell(coord: element.coord, isEditor: true)
                    .environmentObject(rewards)
            }
        }
    }
}

上面使用的

rewards
ivar 是作为
ObservableObject
传入的
EnvironmentObject
,它以这种方式计算网格属性...

    private lazy var muteableRewards: [Gift] = initialRewards
    
    var currentReward: Gift {
        get { muteableRewards[currentRewardIndex] }
        
        set {
            guard let index = muteableRewards.firstIndex(where: { $0 == newValue }) else { return }
            currentRewardIndex = index
            muteableRewards[index] = newValue
        }
    }
    
    var grid: [[RewardCell]] { currentReward.unlockedTileMatrix }

它会像这样改变

currentRewardIndex
......

    func nextIndex() {
        currentRewardIndex = currentRewardIndex == rewards.count - 1 ? 0 : currentRewardIndex + 1
    }

RewardGridCell
的构造函数内,它检查是否应该绘制它(
isVisible
属性)并在下面的guard语句中抛出错误:

    func isVisible(atCoord coord: CGPoint) throws -> Bool {
        guard let value = element(atCoord: coord)?.isVisible else {
            throw NullError(type: .optionalIsNil, subject: coord)
        }
        
        return value
    }

    func element(atCoord coord: CGPoint) -> RewardCell? {
        for row in 0..<grid.count {
            for column in 0..<grid[row].count {
                if grid[row][column].coord == coord {
                    return grid[row][column]
                }
            }
        }
        
        return nil
    }

绘制的第一个网格是5x5,第二个网格是3x3;当 ForEach 尝试坐标 (4,1) 时,它没有元素。我认为我搞砸了可识别一致性,或者也许我没有正确迭代多维数组。 为什么会发生这种情况?使用 SwiftUI 执行此操作的正确方法是什么?

如果需要,我可以添加更多信息,但我已经尝试包含相关代码。如果我在另一篇文章中错过了答案,或者在写问题时犯了一些错误,我真的很感激在任何反对票之前有一个链接或解释等等......

预先感谢您的时间和耐心。

swift swiftui foreach crash outofrangeexception
1个回答
0
投票

只需删除所有出现的

id: \.self
Hashable
扩展名即可修复它。

© www.soinside.com 2019 - 2024. All rights reserved.