Michał Ziobro
Michał Ziobro

Reputation: 11822

SwiftUI ObservableObject used as EnvironmentObject odd behaviour

I have such ObservableObject that I am injecting into views hierarchy by using environmentObject().

class MenuModel: ObservableObject {

    @Published var selection: Int = 0
    @Published var isMenuOpen: Bool = false

    @Published var tabItems : [TabItem] = [TabItem]()
//    {
//        didSet {
//            objectWillChange.send()
//        }
//    }
    @Published var menuItems : [MenuItem] = [MenuItem]()
//    {
//        didSet {
//            objectWillChange.send()
//        }
//    }

    //var objectWillChange = PassthroughSubject<Void, Never>()
}

And here are issues I do not really understand well: 1. Above code with works correctly, as all properties are @Published. 2. But If I change it to something like this

class Click5MenuModel: ObservableObject {

    @Published var selection: Int = 0
    @Published var isMenuOpen: Bool = false

    var tabItems : [TabItem] = [TabItem]()
    {
        didSet {
            objectWillChange.send()
        }
    }
    var menuItems : [MenuItem] = [MenuItem]()
    {
        didSet {
            objectWillChange.send()
        }
    }

    var objectWillChange = PassthroughSubject<Void, Never>()
}

Then @Published properties stop refreshing Views that depends on this ObservableObject! Why is that. I also tried to add didSet with objectWillChange.send() but this also causes some odd behaviour and code is a little bit awkward.

Does this mean that I can only use ONLY @Published or ONLY objectWillChange approach?

Upvotes: 1

Views: 558

Answers (1)

Asperi
Asperi

Reputation: 258441

Default implementation just works (whenever you have @Published properties). Here is from API declaration:

/// By default an `ObservableObject` will synthesize an `objectWillChange`
/// publisher that emits before any of its `@Published` properties changes:
...
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension ObservableObject where Self.ObjectWillChangePublisher == ObservableObjectPublisher {

    /// A publisher that emits before the object has changed.
    public var objectWillChange: ObservableObjectPublisher { get }
}

so remove the following:

var objectWillChange = PassthroughSubject<Void, Never>()

and use

didSet {
    self.objectWillChange.send()
}

Upvotes: 1

Related Questions