【问题标题】:Cannot remove element from foreach if list row contains a textField in SwiftUI如果列表行在 SwiftUI 中包含文本字段,则无法从 foreach 中删除元素
【发布时间】:2020-12-13 21:12:00
【问题描述】:

我已经阅读了几个解决这个问题的方法,我相信我根据建议做的正确,但是这个简单的代码仍然崩溃。

import SwiftUI

struct AnItem : Identifiable {
    let id = UUID()
    var text: String
}

struct ContentView: View {
    @State private var items : [AnItem] = [AnItem(text: "A"), AnItem(text: "B"), AnItem(text: "C")]
    var body: some View {
        List () {
            ForEach (0 ..< items.count) {
                        index in
                TextField("test", text: $items[index].text)
            }.onDelete(perform: deleteItem)
        }
    }
    private func deleteItem(at indexSet: IndexSet) {
        self.items.remove(atOffsets: indexSet)
    }
}

任何人都有解决方法的想法,或者我可能只是做错了。崩溃说

Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift, line 444

正如其他人所说,只是一个文本小部件就可以正常工作。这似乎是通过使用 TextField 引起的。

【问题讨论】:

  • 您需要使用文本字段吗?或者我可以将其更改为更适合您的解决方案吗?
  • 不,它需要是一个 TextField。我知道它适用于 Text。

标签: foreach swiftui


【解决方案1】:

这是一个可能的解决方案。使用id:\.id 识别项目,然后将 TextField 提取到另一个视图

struct AnItem : Identifiable {
    let id = UUID()
    var text: String
}

struct ContentView: View {
    @State private var items : [AnItem] = [AnItem(text: "A"), AnItem(text: "B"), AnItem(text: "C")]
    
    var body: some View {
        List {
            ForEach(items, id: \.id) { item in
                CustomTextField(item: item)
            }.onDelete(perform: deleteItem)
        }
    }
    private func deleteItem(at indexSet: IndexSet) {
        items.remove(atOffsets: indexSet)
    }

}

struct CustomTextField : View {
    @State var item : AnItem
    
    var body : some View {
        TextField("Test", text: $item.text)
    }
}

【讨论】:

  • 这行得通。谢谢你。我不清楚这是 SwiftUI 应该如何工作还是这是一个错误。
【解决方案2】:

这样做怎么样:

  1. 首先让AnItem 符合Hashable 协议。

    struct AnItem : Identifiable, Hashable {
    let id = UUID()
    var text: String
    }
    
  2. 现在让我们稍微改变一下Foreach 和List:

    List {
        ForEach (items, id: \.self) { item in
            Text("\(item.text)")
        }.onDelete(perform: deleteItem)
    }
    

瞧!现在一切正常!

【讨论】:

  • OP 使用 TextField,而不是 Text。有区别
  • 正确,问题是由我在应用程序中需要的 TextField 引起的。
猜你喜欢
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多