This is a followup question to How to share published model between two view models in SwiftUI?.
In order to make nested published models really publish, I used an approach described here: How to tell SwiftUI views to bind to nested ObservableObjects. So far so good, the manual objectWillChange passing works and the changes are getting published by the parent view model.
But if I'm trying to use custom publishers, which tap into the published nested model, they do not function as I am used to (With regular published properties). Here is a simplified example.
Am I missing something?
import SwiftUI
import Combine
struct ContentView: View {
@StateObject var contentViewModel = ContentViewModel()
var body: some View {
VStack{
// Both toggle together, indicating that objectWillChange works correctly
ModelEditView(model: contentViewModel.model)
ModelEditView(model: contentViewModel.model)
// This toggle binds another not nested published property
Toggle("Not Nested Toggle", isOn: $contentViewModel.isToggled)
// Custom toggleChangedPublisher only works with the not nested property
Text(contentViewModel.internalChangedValue ? "true" : "false")
}
}
}
class Model: ObservableObject {
@Published var nestedIsToggled = false
}
class ContentViewModel: ObservableObject {
//Nested Model
@Published var model = Model()
//Not nested model equivalent
@Published var isToggled = false
//Property only altered by the custom toggleChangedPublishers
@Published var internalChangedValue = false
var anyCancellables = Set<AnyCancellable>()
init() {
// This should notify the "parent" ContentViewModel of changes in nested model
anyCancellables.insert(model.objectWillChange.sink { [weak self] (_) in
self?.objectWillChange.send()
})
nestedToggleChangedPublisher
.receive(on: RunLoop.main)
.assign(to: \.internalChangedValue, on: self)
.store(in: &anyCancellables)
toggleChangedPublisher
.receive(on: RunLoop.main)
.assign(to: \.internalChangedValue, on: self)
.store(in: &anyCancellables)
}
private var nestedToggleChangedPublisher: AnyPublisher<Bool, Never> {
// Not working on change of model
$model
.map({return $0.nestedIsToggled})
.eraseToAnyPublisher()
}
private var toggleChangedPublisher: AnyPublisher<Bool, Never> {
// Is working when toggled
$isToggled
.eraseToAnyPublisher()
}
}
Thanks for your support!