SwiftUI onDelete List with Toggle

好久不见. 提交于 2020-08-19 16:54:21

问题


This is my third question on this issue. So far there was no solution that didn't crash. I want to swipe-delete on a List with Toggles. My (simplified) code looks like this:

struct Item: Identifiable {
    var id = UUID()
    var isOn: Bool
}
struct ContentView: View {
    @State var items = [Item(isOn: true) , Item(isOn: false), Item(isOn: false)]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items) {item in
                        Toggle(isOn: self.selectedItem(id: item.id).isOn)
                        {Text("Item")}
                }.onDelete(perform: delete)
            }
        }
    }
    
    func delete(at offsets: IndexSet) {
        self.items.remove(atOffsets: offsets)
    }
    
    func selectedItem(id: UUID) -> Binding<Item> {
        guard let index = self.items.firstIndex(where: {$0.id == id}) else {
            fatalError("Item does not exist")
        }
        return self.$items[index]
    }
    
}

I tried different solutions, e.g. with .indices and .enumerated() and looping over the indices. The solution with the func selectedItem() is from https://troz.net/post/2019/swiftui-data-flow/, which is a nice idea to get a Bindable from item.

If I try to swipe-delete the list items, I always get this error:

Thread 1: Fatal error: Index out of range

I'd really like to understand why this happens, but XCodes error messages doesn't really help. I posted similar questions here: SwiftUI ForEach with .indices() does not update after onDelete (see comment) and here: SwiftUI: Index out of range when deleting cells with toggle.

I really hope someone can help on this issue, because I try to find a solution on the internet for a few days but none of the suggested solutions really worked out for me.

Thanks, Nico


回答1:


Here is fixed part of code (tested with Xcode 11.4 / iOS 13.4)

func selectedItem(id: UUID) -> Binding<Item> {
    guard let index = self.items.firstIndex(where: {$0.id == id}) else {
        fatalError("Item does not exist")
    }

    // Don't use direct biding to array element as it is preserved and
    // result in crash, use computable standalone binding instead !!
    return Binding(get: {self.items[index]}, set: {self.items[index] = $0})
}


来源:https://stackoverflow.com/questions/62948754/swiftui-ondelete-list-with-toggle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!