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。也可以看看:
所以我的问题是:
- 我在这里错过了什么吗?我是 SwiftUI 的新手,所以我很可能根本不了解。
- 我可以在 ForEach 循环中使用绑定,同时还使用
UUID
作为 id (not: id: \.self
) 吗?
- 我能否使 ForEach 循环中的项目如此可识别,以便在删除它们时没有视觉错误同时还使用
ForEach(0..<users.names.count, id: \.self)
?
您可以使用 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)
}
}
我要放弃了。问题在于:我尝试将数组 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。也可以看看:
所以我的问题是:
- 我在这里错过了什么吗?我是 SwiftUI 的新手,所以我很可能根本不了解。
- 我可以在 ForEach 循环中使用绑定,同时还使用
UUID
作为 id (not:id: \.self
) 吗? - 我能否使 ForEach 循环中的项目如此可识别,以便在删除它们时没有视觉错误同时还使用
ForEach(0..<users.names.count, id: \.self)
?
您可以使用 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)
}
}