[Second review] SE-0395: Observability

So that chaining won't be needed first off; the indirect value when composed with other values will be tracked. So the code is considerably more simple than you might have expected:

// View

struct SomeView: View {

  @State private var model = InternalObservable()

  var body: some View {
    VStack {
      Text("\(model.external.directlyObservedProperty)")
      Text("\(model.dependentProperty)")
    }
  }
}


// Internal Observable

@Observable
final class InternalObservable {

  var dependentProperty: String {
    "\(external.indirectlyObservedProperty). Woohoo!"
  }
  let external = ExternalObservable()

  init() { }
}

// Some other module

@Observable
public final class ExternalObservable {

  public var directlyObservedProperty = "Some Value"
  public var indirectlyObservedProperty = "Some Value"
	
  // Calling this method affects both text fields in the View.
  // The changes _are_ guaranteed to be coalesced into
  // a single view update!
  public func updateBothProps() {
    self.directlyObservedProperty = "I'm changing"
    self.indirectlyObservedProperty = "And so am I!"
  }
}

However if you do have a need to (in non SwiftUI scenarios) to do something similar then the use for the withObservationTracking (note; it got changed to a free floating function).

func resetObservationOnExternalObservable() {
    ObservationTracking.withTracking {
      self.dependentProperty = "\(external.indirectlyObservedProperty). Woohoo!"
    } onChange: { [weak self] in
      // The onChange is fired on the willSet side of things - so the reset needs to be called asynchronously to prevent a recursion and also update after the property changes.
      Task { @MainActor in
        self?.resetObservationOnExternalObservable()
      }
    }
  }