# What is the correct way to observe the changes from within a nested \`ObservableObject\`?

**URL:** <https://forums.swift.org/t/what-is-the-correct-way-to-observe-the-changes-from-within-a-nested-observableobject/62788>\
**Category:** Using Swift\
**Tags:** combine\
**Created:** [January 25, 2023, 6:06pm UTC](https://forums.swift.org/t/what-is-the-correct-way-to-observe-the-changes-from-within-a-nested-observableobject/62788 "2023-01-25T18:06:05Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![ole](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ole/32/18720_2.png) [@ole](https://forums.swift.org/u/ole)\
**Post date:** [January 26, 2023, 12:03pm UTC](https://forums.swift.org/t/what-is-the-correct-way-to-observe-the-changes-from-within-a-nested-observableobject/62788/7 "2023-01-26T12:03:34Z")

</div>

> [@ylorn](#):
>
> But it is cumbersome and requires manual collection of all `ObservableObject`s, is there a more concise way to achieve this or some property wrappers that implicitly does it?

I wrote a property wrapper named `@Republished` to encapsulate this pattern. To use it, you'd write the outer class like so:

```swift
final class AggregatedController: ObservableObject {
    @Republished var stringController: StringController
    @Republished var intController: IntController

    init() {
        self.stringController = .init()
        self.intController = .init()
    }
}

```

Notes on my code:

- It's largely untested. I wrote this for fun and never used it in production.

- It uses the unofficial "enclosing self" feature of property wrappers

- Keep in mind [this note from Philippe Hausler](https://forums.swift.org/t/can-published-be-implemented-in-swift/59057/2) that performance may degrade if your root class has no `@Published` property at all (and no custom `objectWillChange` publisher). I think is because in this case Combine stores the object's publisher in some sort of global lookup table.

```swift
import Combine

@propertyWrapper
struct Republished<Obj: ObservableObject> {
    private var storage: Obj
    private var subscription: AnyCancellable? = nil

    init(wrappedValue: Obj) {
        self.storage = wrappedValue
    }

    @available(*, unavailable, message: "Republished can only be used inside reference types that conform to ObservableObject")
    var wrappedValue: Obj {
        get { fatalError() }
        set { fatalError() }
    }

    static subscript<EnclosingSelf: ObservableObject>(
        _enclosingInstance enclosing: EnclosingSelf,
        wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Obj>,
        storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Republished<Obj>>
    ) -> Obj where EnclosingSelf.ObjectWillChangePublisher == ObservableObjectPublisher {
        get {
            // Connect child's objectWillChange to parent's objectWillChange.
            if enclosing[keyPath: storageKeyPath].subscription == nil {
                let parentPublisher = enclosing.objectWillChange
                let childPublisher = enclosing[keyPath: storageKeyPath].storage.objectWillChange
                enclosing[keyPath: storageKeyPath].subscription = childPublisher.sink { _ in
                    parentPublisher.send()
                }
            }

            return enclosing[keyPath: storageKeyPath].storage
        }
        set {
            // Cancel old child's connection to parent.
            if enclosing[keyPath: storageKeyPath].subscription != nil {
                enclosing[keyPath: storageKeyPath].subscription = nil
            }

            enclosing[keyPath: storageKeyPath].storage = newValue

            // Connect new child's objectWillChange to parent's objectWillChange.
            let parentPublisher = enclosing.objectWillChange
            let childPublisher = newValue.objectWillChange
            enclosing[keyPath: storageKeyPath].subscription = childPublisher.sink { _ in
                parentPublisher.send()
            }

            // Must tell parent explicitly that it has changed.
            parentPublisher.send()
        }
    }
}

```

---

_[View the full topic](https://forums.swift.org/t/what-is-the-correct-way-to-observe-the-changes-from-within-a-nested-observableobject/62788)._
