我创建了一个琐碎的项目,试图更好地理解这一点。下面的代码。
我有一个数据源(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()
}
}
答案 0 :(得分:0)
当MyObject
是类类型时,results
包含引用,因此当您更改results
内任何实例的属性时,该实例的引用不会更改,因此{{1} }不会更改,因此不会发布任何内容,也不会更新UI。
在这种情况下,解决方案是在执行内部模型的任何更改时强制显式发布
results