How to implement delete and move function using SwiftUI framework

Viewed 4260

Not able to delete and move row at for the item in the list view.

Apple provided in their training video these methods but its not working

For removing:

array.remove(atOffsets: IndexSet)

For moving:

array.move(fromOffsets: IndexSet, toOffset: Int)

Both of these method are not available in the apple documentation.

Simulator Screen

3 Answers

These methods are part of the Swift 5.1 standard library, which Apple will make available with a future beta of Xcode. In the meantime, you can use these extensions:

extension Array {
    mutating func remove(atOffsets offsets: IndexSet) {
        let suffixStart = halfStablePartition { index, _ in
            return offsets.contains(index)
        }
        removeSubrange(suffixStart...)
    }

    mutating func move(fromOffsets source: IndexSet, toOffset destination: Int) {
        let suffixStart = halfStablePartition { index, _ in
            return source.contains(index)
        }
        let suffix = self[suffixStart...]
        removeSubrange(suffixStart...)
        insert(contentsOf: suffix, at: destination)
    }

    mutating func halfStablePartition(isSuffixElement predicate: (Index, Element) -> Bool) -> Index {
        guard var i = firstIndex(where: predicate) else {
            return endIndex
        }

        var j = index(after: i)
        while j != endIndex {
            if !predicate(j, self[j]) {
                swapAt(i, j)
                formIndex(after: &i)
            }
            formIndex(after: &j)
        }
        return i
    }

    func firstIndex(where predicate: (Index, Element) -> Bool) -> Index? {
        for (index, element) in self.enumerated() {
            if predicate(index, element) {
                return index
            }
        }
        return nil
    }
}

the methods you are refering to are now available on Xcode 11 GM. You can use them like this.

removing an element

TLDR:

.onDelete{offsets in
            self.array.remove(atOffsets: offsets)

full code (can copy paste): import SwiftUI

struct MyTableView : View {

@State var array=[1,2,3,4,5]

var body: some View {

    List{
        ForEach(array,id:\.self){element in
            Text("\(element)")
        }
        .onDelete{offsets in
            self.array.remove(atOffsets: offsets)

        }
    }

    }
}


struct MyTableView_Previews : PreviewProvider {
    static var previews: some View {
        MyTableView()
    }
}

moving elements

.onMove { (offsets, targetOffset) in
            self.array.move(fromOffsets: offsets, toOffset: targetOffset)
        }

They either used custom extensions to Array or some version of Swift not available to the public yet. Workarounds that I implemented are:

delete


func delete(at offsets: IndexSet) {
    if let first = offsets.first {
        store.rooms.remove(at: first)
    }
}

move


func move(from source: IndexSet, to destination: Int) {
    if let first = source.first {
        store.rooms.swapAt(first, destination)
    }
}

Move function works however, the animation is not as good as the one on video at WWDC 2019.

Related