我有一个ForEach块和一个Stepper嵌入在List视图中。List视图第一部分的内容如下:
ForEach(record.nodes.indices, id: \.self) { index in
HStack {
TextField("X", text: self.$record.nodes[index].xString)
Spacer()
Divider()
TextField("Y", text: self.$record.nodes[index].yString)
Spacer()
}
}
Stepper("± node", onIncrement: {
self.record.nodes.append(Node(x: 0, y: 0))
}, onDecrement: {
self.record.nodes.removeLast()
})
Run Code Online (Sandbox Code Playgroud)
我面临的问题是,在调用 时self.record.nodes.removeLast(),应用程序因Index out of range错误而崩溃。我一直试图解决这个问题几个小时,但无济于事。
我最初使用onDelete,但是产生了同样的问题。
该项目可以在https://github.com/jacobcxdev/Timekeeper找到,此错误发生在RecordDetailView.swift 中。
Kou*_*iga 12
索引超出范围错误的发生是因为init(_ data: Range<Int>, content: @escaping (Int) -> Content)初始化ForEach器不允许我们动态修改数组。为此,我们需要init(_ data: Data, content: @escaping (Data.Element) -> Content)像@Asperi 在评论中解释的那样使用初始化程序。但是,正如@JacobCXDev 在回复中所澄清的那样,它在嵌套绑定的这种情况下也不起作用。
使用自定义绑定和附加状态。自定义绑定解决了ForEach过度嵌套绑定的问题。最重要的是,您需要在每次触摸自定义绑定后修改状态以重新渲染屏幕。以下是一个简化的(未经测试的)代码示例。
@State private var xString: String
Run Code Online (Sandbox Code Playgroud)
ForEach(record.nodes) { node in
let xStringBinding = Binding(
get: { node.xString },
set: {
node.xString = $0
self.xString = $0
}
)
TextField("X", text: xStringBinding)
}
Run Code Online (Sandbox Code Playgroud)
只需为子项定义一个视图结构,如下所示。
ForEach(record.nodes) { node in
NodeView(node: node)
}
Run Code Online (Sandbox Code Playgroud)
struct NodeView: View {
@ObservedObject var node: Node
var body: some View {
TextField("X", text: self.$node.xString)
}
}
class Node: ObservableObject, Identifiable {
@Published var xString: String
let id: String = UUID().uuidString
init(xString: String) {
self.xString = xString
}
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理如下代码。
\n\n struct Node {\nvar xString: String = "x"\nvar yString: String = "y"\nvar x: Int\nvar y: Int\n }\n\n struct RecordsNode {\nvar nodes : [Node]\n }\n\nstruct ContentView: View {\n\n\n\n@State var record: RecordsNode = RecordsNode(nodes: [Node(x: 11, y: 11)])\n\nvar body: some View {\n\n Group{\n ForEach(record.nodes.indices, id: \\.self) { index in\n HStack {\n TextField("X", text: self.$record.nodes[index].xString)\n Spacer()\n Divider()\n TextField("Y", text: self.$record.nodes[index].yString)\n Spacer()\n }\n }\n Stepper("\xc2\xb1 node", onIncrement: {\n self.record.nodes.append(Node(x: 0, y: 0))\n }, onDecrement: {\n self.record.nodes.removeLast()\n })}\n\n}}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4329 次 |
| 最近记录: |