2

我在删除包含切换的单元格时遇到问题。

我的模型如下所示:

class Model: ObservableObject {
    @Published var items: [Item]
    
    init(items: [Item]) {
        self.items = items
    }
}

struct Item: Identifiable {
    var id = UUID()
    var text: String
    var isImportant: Bool
}

我的观点是:

struct ContentView: View {
    @EnvironmentObject var model: Model

    var body: some View {
        List {
            ForEach(model.items) {item in
                ItemCell(item: item).environmentObject(self.model)
            }
        .onDelete(perform: deleteItem)
        }
    }
    
    func deleteItem(indexSet: IndexSet) {
        indexSet.forEach({model.items.remove(at: $0)})
    }
}

struct ItemCell: View {
    @EnvironmentObject var model: Model
    var item: Item
    var itemIndex: Int {model.items.firstIndex(where: {$0.id == item.id})!}

    var body: some View {
        Toggle(isOn: $model.items[itemIndex].isImportant) {
            Text(item.text)
        }
    }
}

如您所见,我使用@EnvironmentObject. 每次我尝试删除单元格时,都会收到以下错误消息AppDelegate

Thread 1: Fatal error: Index out of range

我认为问题在于我如何将数据从 myContentView()传递到ItemCell(). 我还尝试将代码集成ItemCell()到闭包中,ForEach但这不起作用。

希望可以有人帮帮我。

附加问题:使用 EnvironmentObject ( ) 注入的目的是什么.environmentObject(self.model)?我不明白什么时候使用它,什么时候不使用它。据我了解,EnvironmentObject 是一个全局对象,它存在于环境中,并且始终更新信息,独立于视图。

谢谢!尼科

更新:

我有另一个想法,但也没有用 ContentView::

ForEach(model.items.indices) {index in
  ItemCell(item: self.$model.items[index]).environmentObject(self.model)
}

ItemCell

@Binding var item: Item
  var body: some View {
    Toggle(isOn: $item.isImportant) {
      Text(item.text)
  }
}

有任何想法吗?

更新 2

这也不起作用:

ForEach(Array(model.items.enumerated()), id: \.element) {index, item in
  ItemCell(item: self.$model.items[index]).environmentObject(self.model)
}
4

1 回答 1

0

一种可能的解决方案是使用默认值而不是强制展开。当您删除列表中的一行时,它的ItemCell视图可能仍然存在于内存中。通过使用默认值,您可以防止崩溃(不存在操作错误项目的风险,因为您无法再访问此视图)。

var itemIndex: Int { model.items.firstIndex(where: { $0.id == item.id }) ?? 0 }

或者,您可以使用可选索引:

struct ItemCell: View {
    @EnvironmentObject var model: Model
    var item: Item
    var itemIndex: Int? { model.items.firstIndex(where: { $0.id == item.id }) }

    var body: some View {
        Group {
            if itemIndex != nil {
                Toggle(isOn: $model.items[itemIndex!].isImportant) {
                    Text(item.text)
                }
            }
        }
    }
}
于 2020-07-19T16:13:20.397 回答