在不使用索引的情况下更新 ForEach 的元素时更新状态

Update State when element of ForEach is updated without using Index

我有以下简单的 ContentView:

struct ContentView: View {

@State private var matrix = [BoxModel(id: 0), BoxModel(id: 1), BoxModel(id: 2)]
@State private var chosen = BoxModel(id: -1)

var body: some View {
    NavigationView {
        GeometryReader { geometry in
            ScrollView {
                VStack {

                    let columns = [GridItem(.fixed(50), spacing: 0),
                                     GridItem(.fixed(50), spacing: 0),
                                     GridItem(.fixed(50), spacing: 0)]
                    

                    LazyVGrid(columns: columns, spacing: 0 ) {
                        ForEach(matrix) { box in
                            Button {
                                chosen = box
                            } label: {
                                Text("\(box.number)")
                            }
                        }
                    }
                    .padding()
                    Button {
                        chosen.number = 5
                    } label: {
                        Text("Click Me")
                    }
                }
            }
        }
    }
}
}

其中 BoxModel 是这样的对象:

struct BoxModel: Codable, Identifiable, Hashable {
    var id: Int
    var number: Int
}

当按下按钮时,我希望“框”更新为新号码。但我想在不使用索引的情况下执行此操作。我知道如果我得到盒子的索引,我可以做一些像 matrix[0].number = 5 这样的事情,它会起作用。

这可能吗?

您的代码显示了包含在 matrix 数组中的框,同时您还创建了 chosen,这是一个完全不同的实例。

您将 chosen 更改为将 5 存储在“数字”属性 中,我敢打赌它正在发生变化,但您仍然只在 UI 中显示框的实例在 matrix 数组内,无论 chosen 发生什么,都不会在屏幕上看到。

您需要完全删除 chosen 变量,并有一个按钮可以更改 matrix 中“框”的每个 实例 。您可能也想将 ForEach 中的代码移动到另一个视图;该视图将具有自己的 BoxModel 类型的 @State var,因此您可以看到发生的变化。