【问题标题】:Indices don't update when deleting item from list从列表中删除项目时索引不更新
【发布时间】:2021-04-22 03:58:39
【问题描述】:

我想创建一个视图,我可以将数组传递到该视图中并让视图编辑数组。下面的代码是一个简化的例子:

struct Item: Identifiable {
  var name: String
  var id = UUID()
}

struct EditItems: View {
  @Binding var item_list: [Item]
  
  var body: some View {
    List {
      ForEach(item_list.indices) { idx in
        Text(item_list[idx].name)
      }
      .onDelete(perform: deleteItem)
    }
    .toolbar {
      ToolbarItem(placement: .principal) {
        EditButton()
      }
    }
  }
  
  func deleteItem(at offsets: IndexSet) {
    item_list.remove(atOffsets: offsets)
  }
}

这首先编译并运行。我可以点击“编辑”并删除列表项。删除列表项后,当我点击“完成”时,我得到“致命错误:索引超出范围”。调试器告诉我,我的列表有 7 个项目,但 Text(item_list[idx].name) 行正在尝试使用 idx = 7 执行。

因此,在删除项目后,ForEach 似乎仍在旧索引上运行,而不是新的较短索引。这是因为item_list 不是@State?当我尝试同时使用@State@Binding 时,我遇到了一堆错误。

我该如何解决这个问题?

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    ForEach 的初始化器接受一个范围,只能用于常量数据。

    来自Apple's docs

    实例只读取提供的数据的初始值并且 不需要跨更新识别视图。

    使用其他 ForEach 初始化器之一,例如:

    ForEach(item_list.enumerated(), id: \.self) { idx, element in
    

    【讨论】:

    • 好吧,我会的,我从来没有注意到其中一些是恒定的,而另一些则不是。谢谢!
    【解决方案2】:

    您使用了 ForEach 的构造函数,它创建 constant 容器,使用不同的容器,带有显式标识符,例如

    List {
      ForEach(item_list.indices, id: \.self) { idx in    // << here !!
        Text(item_list[idx].name)
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-28
      • 2022-01-10
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-07
      相关资源
      最近更新 更多