SwiftUI ForEach index out of range error when removing row

前端 未结 3 921
日久生厌
日久生厌 2021-01-06 00:39

I have a ForEach block and a Stepper embedded in a List view. The contents of the List view\'s first section is as follow

3条回答
  •  一个人的身影
    2021-01-06 01:29

    Problem Description

    The index out of range error occurs because init(_ data: Range, content: @escaping (Int) -> Content) initializer of ForEach does not allow us to modify the array dynamically. For that, we need to use init(_ data: Data, content: @escaping (Data.Element) -> Content) initializer as @Asperi explained in the comment. However, it does not work either in this situation, where bindings are nested, as @JacobCXDev clarified in the reply.

    Workaround (I found a better solution, see below)

    Use custom bindings and an additional state. The custom bindings solve the issue of ForEach over nested bindings. On top of that, you need to modify a state after every touch on the custom binding to re-render the screen. The following is a simplified (untested) code sample.

    @State private var xString: String
    

    ForEach(record.nodes) { node in
        let xStringBinding = Binding(
            get: { node.xString },
            set: {
                node.xString = $0
                self.xString = $0
            }
        )
        TextField("X", text: xStringBinding)
    }
    

    Solution (added on July 10, 2020)

    Just define a view struct for the children like the following.

    ForEach(record.nodes) { node in
        NodeView(node: node)
    }
    

    struct NodeView: View {
        @ObservedObject var node: Node
    
        var body: some View {
            TextField("X", text: self.$node.xString)
        }
    }
    

提交回复
热议问题