I noticed I can mark reference type variables @Published. But then nothing works: changing the contents of this variable doesn't update UI, view's body is not called, class Equatable method is not called.
is it supported to have reference type values @Published?
totally fine with me if it isn't, but then:
assuming the answer "no", is it a bug that I can mark reference type values @Published?
import SwiftUI
struct Some: Equatable {
var x: Int = 0
init(x: Int) {
self.x = x
}
static func == (a: Self, b: Self) -> Bool {
fatalError("to see if it's called")
}
}
class MyClass: Equatable {
var name: String
var some = Some(x: 0)
static func == (a: MyClass, b: MyClass) -> Bool {
fatalError("to see if it's called")
}
init(name: String) {
self.name = name
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
some.x += 1 // neither this
some = Some(x: some.x + 1) // nor that
print("changing mine \(some.x)")
}
}
}
class Model: ObservableObject {
static let singleton = Model()
private init() {}
@Published var item = MyClass(name: "Test")
}
struct ContentView: View {
@ObservedObject var model = Model.singleton
var body: some View {
print("body")
return Text(model.item.name + String(model.item.some.x)).padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
This is expected and not a bug as, while observing the mutations of a references address isn't usually interesting, there may be a few cases where it is.
No, I mean that, like all property wrappers, Published relies on mutation observation to trigger. Mutation the state of a reference type is not visible to this type of observation, so you see what you see. However, if you were to mutate the reference itself, perhaps by reassigning it, you should see a published value. Usually that's not useful at all but it could be sometimes, hence the lack of restriction on Published.Value.