1

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?

2
  • Do you want just to know the reason or how to make it work? Because by my tests removing your locally defined objectWillChange and use instead inherited from ObservableObject in didSet, ie. didSet { self.objectWillChange.send() } updates view as expected. Just in case. Commented Nov 26, 2019 at 12:58
  • objectWillChange is my locally define? so I shouldn't place it at all? I added this as most examples use it, but as you say I should only call it in didSet ? Commented Nov 26, 2019 at 13:16

1 Answer 1

1

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()
}
Sign up to request clarification or add additional context in comments.

1 Comment

I think you have to expect odd behavio(u)r when using didSet instead of willSet to call objectWillChange. Useful discussion here: pointfree.co/blog/posts/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.