首页 > 解决方案 > 嵌套数组中的已发布变量不显示更改

问题描述

我有一个数组(foos),其中包含另一个数组(bars),它有一个已发布的 var isExpanded。对于每个 Bar,我想根据 isExpanded 的状态显示一个图像。

我的问题在于单击切换布尔值的按钮时图像不会改变。

class Bar: ObservableObject, Identifiable {
    @Published var isExpanded = false
    var id = UUID()
}

class Foo: ObservableObject, Identifiable {
    @Published var bars:[Bar] = []
    var id = UUID()
}

class FooList: ObservableObject {
    @Published var foos:[Foo] = []

    init(array: [Foo]) {
        foos = array
    }
}

struct ContentView: View {
    @ObservedObject var fooList:FooList = createFoos()

    var body: some View {
        VStack {
            ForEach(fooList.foos) { foo in
                ForEach(foo.bars) { bar in
                    Button(action: {
                        bar.isExpanded.toggle()
                    }, label: {
                        if bar.isExpanded {
                            Image(systemName: "minus.app")
                        } else {
                            Image(systemName: "plus.app")
                        }
                    })
                }
            }
        }
    }
}

func createFoos() -> FooList {
    var foos = [Foo]()
    for x in 0...5 {
        let foo = Foo()
        for y in 0...5 {
            let bar = Bar()
            foo.bars.append(bar)
        }
        foos.append(foo)
    }
    return FooList(array: foos)
}

不确定它是否相关,但我还必须创建第三个类 FooList 来保存 foos 数组,因为我无法从对象数组中创建 ObservedObject,例如:

@ObservedObject var fooList:[Foo] = createFoos()

一段时间以来我一直在反对这个,我猜这是我还不理解的一些基本范式。任何帮助表示赞赏!

标签: swiftui

解决方案


将模型从基于引用更改为基于值,这是您期望的行为...

注意:使用类也是可能的,但需要将内部更新交叉连接到外部容器,这由 SwiftUI 观察到,因此更复杂。在任何内部级别改变价值会完全改变模型

所以,这里...

在此处输入图像描述

struct Bar {
    var isExpanded = false
    var id = UUID()
}

struct Foo {
    var bars:[Bar] = []
    var id = UUID()
}

class FooList: ObservableObject {
    @Published var foos:[Foo] = []

    init(array: [Foo]) {
        foos = array
    }
}

struct TestPublishedModelChanged: View {
    @ObservedObject var fooList:FooList = createFoos()

    var body: some View {
        VStack {
            ForEach(Array(fooList.foos.enumerated()), id:\.1.id) { (i, foo) in
                ForEach(Array(foo.bars.enumerated()), id: \.1.id) { (j, bar) in
                    Button(action: {
                        self.fooList.foos[i].bars[j].isExpanded.toggle()
                    }, label: {
                        if self.fooList.foos[i].bars[j].isExpanded {
                            Image(systemName: "minus.square")
                        } else {
                            Image(systemName: "plus.square")
                        }
                    })
                }
            }
        }
    }
}

func createFoos() -> FooList {
    var foos = [Foo]()
    for _ in 0...2 {
        var foo = Foo()
        for _ in 0...2 {
            let bar = Bar()
            foo.bars.append(bar)
        }
        foos.append(foo)
    }
    return FooList(array: foos)
}

推荐阅读