ios – SwiftUI DragGesture stops responding when eradicating the final merchandise in a row of a 2D array mid-gesture

0
18
ios – SwiftUI DragGesture stops responding when eradicating the final merchandise in a row of a 2D array mid-gesture


This happens as a result of the view that’s being dragged is faraway from the view hierarchy.

ForEach makes use of its id: parameter (if it has one) to trace when so as to add/take away views. The outer ForEach creates two inside ForEaches, one for every row. The inside ForEaches makes use of array indices as their ids. That is already a foul concept, given that you will re-order the inside arrays’ parts. See additionally: SwiftUI: Why does ForEach want an ID?

Initially, the IDs for the 2 rows are:

row 1: 0, 1, 2
row 2: 0, 1, 2

The final merchandise of the second row has 2 as its id. Whenever you transfer it, the ids now change into:

row 1: 0, 1, 2, 3
row 2: 0, 1

We see that the id similar to the final merchandise within the second row (i.e. 2) has disappeared from the second row. Because of this, ForEach removes the view from the second row, cancelling the gesture. Then, the ForEach for the primary row provides a brand new view to itself.

In the event you transfer a non-last merchandise, the identical change occurs, however that merchandise’s id won’t be faraway from the second row, so the gesture retains going.

As a proof of idea, should you use just one ForEach, and a extra applicable id, such because the id of the Merchandises, the gesture doesn’t get cancelled.

VStack {
    Textual content("Dragging translation worth: n (translationHeight)")
    LazyVGrid(columns: Array(repeating: .init(.versatile(minimal: 10, most: 50)), depend: 3)) {
        let allIndices = array2d.indices.flatMap { i in
            array2d[i].indices.map { j in (i, j) }
        }
        let _ = print("up to date")
        let flattened = array2d.flatMap { $0 }
        ForEach(Array(flattened.enumerated()), id: .aspect.id) { (i, elem) in
            Textual content(elem.textual content)
                .padding()
                .background(Colour.inexperienced)
                .gesture(
                    DragGesture(coordinateSpace: .world)
                        .onChanged({ worth in
                            translationHeight = worth.translation.top
                            if worth.translation.top > 200 && doItOnce {
                                let (j, ok) = allIndices[i]
                                let temp = array2d[j].take away(at: ok)
                                array2d[0].insert(temp, at: 0)
                                doItOnce = false
                            }
                        })
                        .onEnded({ worth in
                            doItOnce = true
                            translationHeight = 0
                        })
                )
        }
    }
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here