如果列表行在 SwiftUI 中包含文本字段,则无法从 foreach 中删除元素

Posted

技术标签:

【中文标题】如果列表行在 SwiftUI 中包含文本字段,则无法从 foreach 中删除元素【英文标题】:Cannot remove element from foreach if list row contains a textField in SwiftUI 【发布时间】: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。 【参考方案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】:

这样做怎么样:

    首先让AnItem 符合Hashable 协议。

    struct AnItem : Identifiable, Hashable 
    let id = UUID()
    var text: String
    
    

    现在让我们稍微改变一下ForeachList

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

瞧!现在一切正常!

【讨论】:

OP 使用 TextField,而不是 Text。有区别 正确,问题是由我在应用程序中需要的 TextField 引起的。

以上是关于如果列表行在 SwiftUI 中包含文本字段,则无法从 foreach 中删除元素的主要内容,如果未能解决你的问题,请参考以下文章

在另一个字段Oracle SQL中包含的一个字段中查找文本

如何评估访问查询中另一个字段中包含的字段名称?

根据数组中的重复模式更改 SwiftUI 列表中文本字段的第二次出现

导出为 PDF 时如何在文本字段中包含图像和表格?

如何在 MongoDb 驱动程序的列表中包含特定字段

SwiftUI 中带有文本字段的长列表