# Combine ObservableObject in UIKit

**URL:** <https://forums.swift.org/t/combine-observableobject-in-uikit/28433>\
**Category:** Using Swift\
**Tags:** off-topic, combine\
**Created:** [September 1, 2019, 12:16pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433 "2019-09-01T12:16:00Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Zanchee](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/zanchee/32/8870_2.png) [@Zanchee](https://forums.swift.org/u/Zanchee)\
**Post date:** [September 1, 2019, 12:16pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/1 "2019-09-01T12:16:00Z")

</div>

I began messing with combine in one of my personal projects and I am trying to use combine to allow my controllers and views to subscribe to different values in my app state.

I created an app state that has `@Published` properties, and that’s great, I can subscribe to changes on those properties, but in the case of a controller wanting to subscribe to the entire app state, it seems as though the option is only `ObservableObject` My confusion arises in the fact that this protocol exposes `objectWillChange` and not something like `objectDidChange`. Which means when I add a `sink` to it, I’m only ever getting the old value of state instead of the most recent. Am I missing something? Is this there a better way that I’m not aware of?

---

<div class="post-metadata">

**Author:** ![Joseph\_Heck](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joseph_heck/32/22369_2.png) [@Joseph\_Heck](https://forums.swift.org/u/Joseph_Heck)\
**Post date:** [September 17, 2019, 1:18am UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/2 "2019-09-17T01:18:20Z")

</div>

You're not really missing anything here - it's a very focused API endpoint (that I believe was meant to support some of the internals/optimizations of SwiftUI - but I'm asserting that with no detailed knowledge).

the `objectWillChange` publisher's `Output` type is type-aliased to `Void`, so while you'll get a triggered notification, it's also not actually passing any changed values - just the notification that the referenced object was, in fact, changed (or is about to change) in some fashion - so that your code can open up that object and inspect it for what it is after the change.

---

<div class="post-metadata">

**Author:** ![topchul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/topchul/32/9511_2.png) [@topchul](https://forums.swift.org/u/topchul)\
**Post date:** [November 6, 2019, 9:57am UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/3 "2019-11-06T09:57:46Z")

</div>

Hello connor.

`objectWillChange` would publish before set newValue. and `Ouput = Void`  
so, you can not access newValue.

But, you can access newValue next dispatching after change operation.

```
someObservableObject.objectWillChange
    .makeConnectable()
     .autoconnect()
      .sink { [weak self] in
          print(self?.someObservableObject)
          DispatchQueue.main.async { [weak self] in
              print(self?.someObservableObject)
          }
      }

```

this code will print oldValue and newValue.

---

<div class="post-metadata">

**Author:** ![AndyIbanez](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/andyibanez/32/3794_2.png) [@AndyIbanez](https://forums.swift.org/u/AndyIbanez)\
**Post date:** [December 29, 2019, 9:09pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/4 "2019-12-29T21:09:42Z")

</div>

I'm rewriting one of my apps in SwiftUI, and I'm just wondering why the change from didChange to objectWillChange took place.

I find it odd that we can only be notified when something will change and that we have no way to react to the new value.

Currently, I am using @topchul's solution with the DispatchQueue (though I need to do asyncAfter and wait a few milliseconds before I can access a new value), but it just doesn't feel like it is the right solution to this problem. It definitely works, though.

I'm using SwiftUI, and my intention is to know when a certain ObservableObject has a non-nil error I can inspect. Currently, it looks like this:

```swift
        .onReceive(schedule.objectWillChange) { _ in
            // We can also use schedule.objectWillChange to get the publisher.
            DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
                if self.schedule.provider.error != nil {
                    self.showingError = true
                }
            }
        }

```

---

<div class="post-metadata">

**Author:** ![jenox](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jenox/32/5811_2.png) [@jenox](https://forums.swift.org/u/jenox)\
**Post date:** [December 29, 2019, 10:33pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/5 "2019-12-29T22:33:29Z")

</div>

I believe that when an observed object changes, SwiftUI internally simply invalidates the view hierarchy, rerendering and diffing it at a later point, possibly on the next run loop. This would be an important optimization to prevent superfluous rendering passes when an object posts multiple of these notifications in quick succession: Imagine changing two or more of an observed object's properties in the same block of code — this should only result in one rendering pass. I'd imagine this is implemented similar to `setNeedsDisplay()` or `setNeedsLayout()`.

As to why they used 'will change' over 'did change', I am not sure. In an early beta, it actually was called `objectDidChange`! But I guess that with `objectWillChange` it is harder to misuse the API: you are forced to debounce a call to read the new value.

But I, too, have no knowledge of the SwiftUI or Combine internals — so take that with a grain of salt.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [December 29, 2019, 10:53pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/6 "2019-12-29T22:53:22Z")

</div>

I remember reading [this tweet](https://twitter.com/luka_bernardi/status/1151633281982406656).

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [December 29, 2019, 10:59pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/7 "2019-12-29T22:59:46Z")

</div>

> [@AndyIbanez](#):
>
> .onReceive(schedule.objectWillChange) { \_ in // We can also use schedule.objectWillChange to get the publisher. DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) { if self.schedule.provider.error != nil { self.showingError = true } } }

Looks like you could make `showingError` a function of `scheduleProvider`.

```swift
var showingError: Bool {
  schedule.provider.error != nil
}

```

and use that instead of stored property.

---

<div class="post-metadata">

**Author:** ![AndyIbanez](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/andyibanez/32/3794_2.png) [@AndyIbanez](https://forums.swift.org/u/AndyIbanez)\
**Post date:** [December 29, 2019, 11:03pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/8 "2019-12-29T23:03:25Z")

</div>

Thanks. That's insightful, and it does make sense.

---

<div class="post-metadata">

**Author:** ![AndyIbanez](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/andyibanez/32/3794_2.png) [@AndyIbanez](https://forums.swift.org/u/AndyIbanez)\
**Post date:** [December 29, 2019, 11:04pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/9 "2019-12-29T23:04:48Z")

</div>

This is a good idea. Unfortunately it doesn't work for me because I need `showingError` to be a state variable so I can use it with the `.sheet` modifier. I tried something similar to that, but you cannot use property wrappers with computed properties 😞

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [December 29, 2019, 11:33pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/10 "2019-12-29T23:33:00Z")

</div>

Could you provide more code as to what you’re trying to do (And may as well create a separate thread)?

---

<div class="post-metadata">

**Author:** ![AndyIbanez](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/andyibanez/32/3794_2.png) [@AndyIbanez](https://forums.swift.org/u/AndyIbanez)\
**Post date:** [December 30, 2019, 12:47am UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/11 "2019-12-30T00:47:14Z")

</div>

Sure. Right now it's low priority since it works with the dispatch, but I will create a thread later and tag you there so you can take a look at it.

---

<div class="post-metadata">

**Author:** ![Daniel\_Steinberg](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/daniel_steinberg/32/334_2.png) [@Daniel\_Steinberg](https://forums.swift.org/u/Daniel_Steinberg)\
**Post date:** [November 23, 2020, 5:25pm UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/12 "2020-11-23T17:25:27Z")

</div>

I observe the same thing when using objectWillChange from a ViewController (using UIKit).

Is there a recommended approach other than pushing to the main thread using DispatchQueue.main.async or receive(on: RunLoop.main) to get the correct value (after the set - that is) or is that what we're supposed to do?

Just want to make sure I'm teaching good practices.

Thanks,

Daniel

---

<div class="post-metadata">

**Author:** ![ziadtamim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ziadtamim/32/9112_2.png) [@ziadtamim](https://forums.swift.org/u/ziadtamim)\
**Post date:** [August 26, 2021, 9:05am UTC](https://forums.swift.org/t/combine-observableobject-in-uikit/28433/13 "2021-08-26T09:05:37Z")

</div>

`@Published` is effectively very `SwiftUI` focussed, adds a `willSet` property observer to properties so that any changes are automatically sent out to observers.

An alternative to achieve such behavior can be performed as shown below. However, your code should handle the different cases as the object emits multiple notifications on `willSet` and` didSet`

```swift
class Foo: ObservableObject {
    var someProperty: String {
        didSet {
            objectWillChange.send()
        }
    }
}

```
