Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI on macOS: How to enable UI for onDelete (deletion from List)

Tags:

macos

swiftui

Perhaps I'm particularly dense this morning but I'm trying to delete a row from a List in SwiftUI on macOS.

The issue is that there is no UI exposed to perform the delete. By that I mean that the List does not respond to delete key presses, has no right click menu nor supports any other gestures like swipe to delete (which would be odd on macOS anyway).

Here's the example I'm using:

import SwiftUI

struct ContentView: View {
    @State var items = ["foo", "bar", "baz"]
    @State var selection: String? = nil

    var body: some View {
        List(selection: $selection) {
            ForEach(items, id: \.self) { Text($0) }
                .onDelete { self.items.remove(atOffsets: $0)}
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

The exact same code on iOS gives me a table view with the standard "swipe left to delete" UI. On macOS there is just nothing.

I tried adding

    .onDeleteCommand(perform: {
        if let sel = self.selection, let idx = self.items.firstIndex(of: sel) {
            self.items.remove(at: idx)
        }
    })

to the List but still no response to delete key presses.

How does one enable List row deletion on macOS?

like image 703
sas Avatar asked Jan 16 '20 08:01

sas


People also ask

How to remove item from list SwiftUI?

To remove an item from a SwiftUI list, the list view requires a variable to store the item you want to remove. Create an optional for the variable and set it to nil initially. ListItemStruct is the name of the data structure in your app that you want to show in the list.

How do I swipe delete in SwiftUI?

Swipe-to-delete This feature was available in SwiftUI right from the beginning. It is pretty straight-forward to use, but also pretty basic (or rather inflexible). To add swipe-to-delete to a List view, all you need to do is apply the onDelete modifier to a ForEach loop inside a List view.

How do I use onDelete?

When you're ready, swipe from right to left across any of the rows in your list, and you should find a delete button appears. You can tap that, or you can also use iOS's swipe to delete functionality by swiping further.


2 Answers

I am facing the same issue, and I found out two fingers swipe triggering deletion. It crashes with the fatal error since I delete element in onDelete(), and I'm still figuring out how to fix it:

index out of range

Edit: I replaced index to element, and it works fine.

ForEach(elementArray.indices) { index in 
    // code... 
}

to

ForEach(elementArray) { element in 
    // code... 
}

and it works fine :)

like image 127
Octur Avatar answered Sep 27 '22 21:09

Octur


This code enables the "Delete" menu and removes the selected item when I select Edit > Delete (without manually wiring up the menu):

struct ContentView: View {
    @State var items = ["foo", "bar", "baz"]
    @State var selection: String? = nil

    var body: some View {
        List(selection: $selection) {
            ForEach(items, id: \.self) { Text($0) }
        }
        .onDeleteCommand {
            if
                let sel = self.selection,
                let idx = self.items.firstIndex(of: sel) {
                print("delete item: \(sel)")
                self.items.remove(at: idx)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .animation(.default)
    }
}

Then, to make the delete key work, make it the keyboard equivalent for the Delete menu option: - Edit Main.storyboard - Select Edit > Delete - Click in the "Key Equivalent" field - Hit the delete key.

enter image description here

Run the app, select an item, hit the delete key, and your item should disappear.

like image 36
ggruen Avatar answered Sep 27 '22 21:09

ggruen