如何在模型类子属性更改时使SwiftUI视图更新?

时间:2020-06-18 23:54:16

标签: swiftui

我创建了一个琐碎的项目,试图更好地理解这一点。下面的代码。

我有一个数据源(DataSource),其中包含@Published个项的MyObject数组。 MyObject包含一个字符串。按下UI上的按钮会导致MyObject实例之一立即更新,另外还会设置一个计时器,以便在几秒钟后更新第二个实例。

如果MyObject是一个结构,那么一切都会按照我的想象进行。但是,如果MyObject是一个类,则刷新不会触发。

我的期望是,更改结构的值会导致将更改后的实例放置在数组中,从而引发更新链。但是,如果MyObject是一个类,则在引用类型内更改字符串会在数组中保留相同的实例。 Array没有意识到已经发生了变化,因此请不要在我的DataSource中提及。没有UI更新发生。

问题是–当MyObject类的属性更改时,需要做些什么来使UI更新?我试图将MyObject做成ObservableObject并抛出一些didchange.send()指令,但都没有成功(我相信无论如何现在这些都是多余的)。

有人可以告诉我这是否可行,如何更改下面的代码以实现这一目标?如果有人想问为什么我不只是使用结构,那是因为在我的实际项目中我已经尝试过这样做。但是,我使用的数据类型集合会在闭包(对集合中每个项目的并行处理)和其他循环中进行自我修改。我试图将它们重写为结构,但遇到了许多挑战。

import Foundation
import SwiftUI

struct ContentView: View
{
    @ObservedObject var source = DataSource()

    var body: some View
    {
        VStack
        {
            ForEach(0..<5)
            {i in
                HelloView(displayedString: self.source.results[i].label)
            }
            Button(action: {self.source.change()})
            {
                Text("Change me")
            }
        }
    }
}

struct HelloView: View
{
    var displayedString: String

    var body: some View
    {
        Text("\(displayedString)")
    }
}

class MyObject // Works if declared as a Struct
{
    init(label: String)
    {
        self.label = label
    }

    var label: String
}

class DataSource: ObservableObject
{
    @Published var results = [MyObject](repeating: MyObject(label: "test"), count: 5)

    func change()
    {
        print("I've changed")
        results[3].label = "sooner"
        _ = Timer.scheduledTimer(withTimeInterval: 2, repeats: false, block: {_ in self.results[1].label = "Or later"})
    }
}

struct ContentView_Previews: PreviewProvider
{
    static var previews: some View
    {
        ContentView()
    }
}

1 个答案:

答案 0 :(得分:0)

MyObject是类类型时,results包含引用,因此当您更改results内任何实例的属性时,该实例的引用不会更改,因此{{1} }不会更改,因此不会发布任何内容,也不会更新UI。

在这种情况下,解决方案是在执行内部模型的任何更改时强制显式发布

results