【问题标题】:SwiftUI remove array entries within ForEach subviewsSwiftUI 删除 ForEach 子视图中的数组条目
【发布时间】:2021-01-12 11:41:06
【问题描述】:

我是 IOS 开发的新手,如果我以完全不正确的方式使用了代码,请多多包涵。

我使用 swiftui 2,我的问题是我的数据结构中有一个数组,其中包含我想通过 ForEach 在另一个视图中呈现的信息。到目前为止,这是可行的,但是如果我在其中一个子视图中更改数组,则会收到 index out of range 错误

这是示例数据结构

struct Test  {
    var id: String
    var array : Array<String>
}

EnvironmentObject

class DBhandler: ObservableObject {
    
    @Published var arrays: Test
    
    init(arrays: Test) {
        self.arrays = arrays
    }
}

应用文件

@main
struct DummyApp: App {
    @ObservedObject var dbhandler = DBhandler(arrays: Test(id: "1", array: ["Car", "Bus", "Train"]))
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(dbhandler)
        }
    }
}

主视图

struct ContentView: View {
    @EnvironmentObject var dbhandler: DBhandler
    
    var body: some View {

        VStack{
            ForEach(dbhandler.arrays.array.indices, id: \.self) {index in
                SubView(index: index)
            }
        }
        
    }
}

子视图

struct SubView : View {
    @EnvironmentObject var dbhandler: DBhandler
    
    let index: Int
    var body: some View {
        VStack{
            Text(dbhandler.arrays.array[index]) <--- here's the index out of range error
            Button(action: {
                dbhandler.arrays.array.remove(at: index)
            }, label: {
                Text("Remove object")
            })
        }

    }
}

我的假设是 ForEach 不是指最新的 dbhandler.arrays.array.indices 而是指一个旧的存储但我不知道如何规避它。

你们中有人知道我该如何解决这个问题吗?

非常感谢任何帮助:)

【问题讨论】:

  • 嗨 Asperi,如果我在 stackoverflow.com/questions/58984109/… 正确理解您的建议,那么我应该删除 foreach 中的 .indices。但是我需要索引。如果我通过 SubView(index: dbhandler.arrays.array.firstIndex(of: index)!) 生成它,我会遇到最后一个索引的问题。您对如何解决这个问题有什么建议吗?

标签: ios arrays swift swiftui swiftui-environment


【解决方案1】:

对于任何有同样问题的人。我已经找到了实现它的方法。由于ForEach 存储原始数组并且不引用原始数组,因此可能的解决方法是强制ForEach 自我更新。你可以这样做:

struct ContentView: View {
    @EnvironmentObject var dbhandler: DBhandler
    @State var dummyVar : Int = 0

    var body: some View {

        VStack{
            ForEach(dbhandler.arrays.array.indices, id: \.self) {index in
                SubView(index: index, dummyVar : dummyVar)
            }.id(dummyVar)
        }
        
    }
}

在 SubView 中,您只需将 dummyVar 增加 1。

【讨论】:

  • 如何在 SubView 中增加 dummyVar? SubView 是一个结构,因此它正在处理 dummyVar 的副本。更改 SubView 中的 dummyVar 不会更改 ContentView 中的 dummyVar。或者,SubView 有什么方法可以访问 ContentView 中声明的 State 变量吗? (我是 SwiftUI 新手)
  • 是的,您可以将 SubView 中的 dummyVar 声明为 @Binding,然后它将引用回父级 (ContentView)
  • 我假设您在 SubView 的按钮操作中增加 dummyVar。此外,我必须使用 $dummyVar(前面的美元符号)作为 SubView 的参数。感谢您的帮助!
  • 是的,这就是如何使用变量作为绑定:)
【解决方案2】:

您可以通过在 SubView index 中添加检查来修复崩溃,如果索引超出范围,则不会呈现 View

struct SubView : View {
    @EnvironmentObject var dbhandler: DBhandler

    let index: Int
    var body: some View {
    VStack{
        if index < dbhandler.arrays.array.count{
            Text(dbhandler.arrays.array[index]) //<--- here's the index out of range error
            Button(action: {
                dbhandler.arrays.array.remove(at: index)
            }, label: {
                Text("Remove object")
            })
            
            }
        }

    }
}

【讨论】:

  • 嗨@Babar 感谢您的提示。我也想过那个解决方案,但认为必须有一种更简单的方法来处理这个问题。是否有另一种方法可以正确使用 ForEach 或其他方法,这样我就不必为每个子视图实施解决方法?
猜你喜欢
  • 2021-05-02
  • 1970-01-01
  • 2020-02-17
  • 1970-01-01
  • 2023-03-26
  • 2019-11-07
  • 1970-01-01
  • 2020-06-17
相关资源
最近更新 更多