Editbutton 在 SwiftUI 中以一种有趣的方式从列表中删除项目(带绑定)

Editbutton deletes items (with Bindings) from List in a funny way in SwiftUI

我要放弃了。问题在于:我尝试将数组 names 作为列表中的 ObservableObject 加载。名称必须作为 Bindings 连接到文本字段:

class Users: ObservableObject {
    @Published var names = ["Adele", "Taylor", "Michael"]
}

我的 ContentView 看起来像这样:

@EnvironmentObject var users: Users
var body: some View {
    NavigationView {
        List {
            ForEach(0..<users.names.count, id: \.self) {
                TextField("titel", text: $users.names[[=11=]])
            }
            .onDelete(perform: delete)
        }
        .navigationBarItems(trailing: EditButton())
        .navigationTitle("bug")
    }
}
func delete(at offsets: IndexSet) {
    users.names.remove(atOffsets: offsets)
}

环境对象链接到 ContentView():

ContentView()
.environmentObject(Users())

一切正常,但是当我尝试删除一行时,它看起来很有趣:下面的行向右滑动,应该删除的行向上移动。它甚至不一致,但取决于我开始删除的项目。看这个.gif:

到目前为止我尝试过的:

我认为该错误与无法识别的列表有关。所以我尝试使用类似的东西:

ForEach(users.names, id: \.id) {
    ...
}

新用户 class 和 id: UUID() 但是使用对象本身而不是 0..<users.names.count 只会导致问题,我不能在我的 ForEach-Loop 中使用 Binding。也可以看看:

所以我的问题是:

您可以使用 enumerated 访问 element 及其 index:

ForEach(Array(users.names.enumerated()), id: \.element.id) { index, element in
    // use either `index` or `element` here
}

您还可以使用此 来确保您在删除项目时不会访问不存在的绑定。

@pawello and @George_E 的帮助下,我的工作代码现在看起来像这样:

struct UserWithUUID: Identifiable {
    var id: UUID
    var name: String
}

class Users: ObservableObject {
    @Published var names = [UserWithUUID(id: UUID(), name: "Taylor"), UserWithUUID(id: UUID(), name: "Swift")]
}

struct ContentView: View {
    @EnvironmentObject var users: Users
    
    var body: some View {
        NavigationView {
            List {
                ForEach(Array(users.names.enumerated()), id: \.element.id) { index, element in
                    TextField("titel", text: Binding<String>(get: { element.name }, set: { users.names[index].name = [=10=] }))
                }
                .onDelete(perform: delete)
            }
            .navigationBarItems(trailing: EditButton())
            .navigationTitle("working")
        }
    }
    func delete(at offsets: IndexSet) {
        users.names.remove(atOffsets: offsets)
    }
}