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?
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.
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.
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.
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 :)
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.
Run the app, select an item, hit the delete key, and your item should disappear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With