Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI map @Published var from one ObservableObject to another

I would like two separate ObjservableObject to share a single @Published var. Ideally something like the below. That does not compile due to Cannot assign to property: '$bar' is immutable. I would like foo and bar to be in sync if a change is made to one or the other.

class FooState: ObservableObject {
    @Published var foo: Bool = false
}

class BarState: ObservableObject {
    @Published var bar: Bool

    init(fooState: FooState) {
        self.$bar = fooState.$foo // compile error
    }
}

let fooState = FooState()
let barState = BarState(fooState: fooState)

print(fooState.foo) // false
print(barState.bar) // false

fooState.foo = true
print(fooState.foo) // true
print(barState.bar) // true
like image 308
Kris Gellci Avatar asked Dec 15 '25 04:12

Kris Gellci


1 Answers

This is not currently supported (I think). The only way I know to work around it is subscribing to the nested observable object yourself and propagating the objectWillChange event:

class FooState: ObservableObject {
    @Published var foo: Bool = false
}

class BarState: ObservableObject {
    var fooState: FooState

    var bar: Bool {
        return self.fooState.foo
    }

    private var cancellables = Set<AnyCancellable>()

    init(fooState: FooState) {
        self.fooState = fooState

        fooState.objectWillChange
            .sink { [weak self] in
                self?.objectWillChange.send()
            }
            .store(in: &cancellables)
    }
}

let fooState = FooState()
let barState = BarState(fooState: fooState)

print(fooState.foo) // false
print(barState.bar) // false

fooState.foo = true
print(fooState.foo) // true
print(barState.bar) // true
like image 87
gabriellanata Avatar answered Dec 16 '25 20:12

gabriellanata



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!