我指的是我已经问过的两个问题,Asperi回答得很好:SwiftUI ForEach with .indices() does not update after onDelete, SwiftUI onDelete List with Toggle
现在,我尝试使用ForEach
修改NavigationLink
中的闭包,突然,应用再次崩溃,
Thread 1: Fatal error: Index out of range
当我尝试滑动删除时。
代码:
class Model: ObservableObject {
@Published var name: String
@Published var items: [Item]
init(name: String, items: [Item]) {
self.name = name
self.items = items
}
}
struct Item: Identifiable {
var id = UUID()
var isOn: Bool
}
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
NavigationView {
List {
ForEach(model.items) {item in
NavigationLink(destination: DetailView(item: self.makeBinding(id: item.id))) {
Toggle(isOn: self.makeBinding(id: item.id).isOn)
{Text("Toggle-Text")}
}
}.onDelete(perform: delete)
}
}
}
func delete(at offsets: IndexSet) {
self.model.items.remove(atOffsets: offsets)
}
func makeBinding(id: UUID) -> Binding<Item> {
guard let index = self.model.items.firstIndex(where: {$0.id == id}) else {
fatalError("This person does not exist")
}
return Binding(get: {self.model.items[index]}, set: {self.model.items[index] = $0})
}
}
struct DetailView: View {
@Binding var item: Item
var body: some View {
Toggle(isOn: $item.isOn) {
Text("Toggle-Text")
}
}
}
它在没有NavigationLink
或没有Toggle
的情况下有效。因此在我看来,在此闭包中我只能使用一次makeBinding
-Function。
感谢帮助
答案 0 :(得分:0)
即使没有导航链接,您的代码也崩溃了。有时仅当我删除数组中的最后一个对象时。看起来它仍在尝试从数组中访问索引。与您上面链接的示例的区别在于,它们没有使用EnvironmentObject
来访问数组。将数组直接存储在@State
中。
我想出了一些不同的方法,将Item声明为ObservedObject
,然后将其简单地传递给子视图,您可以在其中将其值用作Binding,而无需任何功能。
我将商品更改为..
class Item: ObservableObject {
var id = UUID()
var isOn: Bool
init(id: UUID, isOn: Bool)
{
self.id = id
self.isOn = isOn
}
}
将ContentView更改为此。
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
NavigationView {
List {
ForEach(model.items, id:\.id) {item in
NavigationLink(destination: DetailView(item: item)) {
Toggler(item: item)
}
}.onDelete(perform: delete)
}
}
}
我将Toggle外包给了另一个视图,我们将ObservedObject传递到了另一个视图,对于DetailView也是一样。
struct Toggler: View {
@ObservedObject var item : Item
var body : some View
{
Toggle(isOn: $item.isOn)
{Text("Toggle-Text")}
}
}
struct DetailView: View {
@ObservedObject var item: Item
var body: some View {
Toggle(isOn: $item.isOn) {
Text("Toggle-Text")
}
}
}
它们都将Item
用作ObservedObject,并将其用作Toggle
的绑定。