Tracking properties in `@Observable` models internally

I found a solution from two parts:

  1. This gist that returns a publisher for a given keypath. The downside is there's no way to limit the keypath parameter to @ObservationTracked keypaths only, so a publisher can be formed for @ObservationIgnored keypaths.
  2. This gist from @jasdev that lets you assign to weakly captured self, as Combine's assign(to:on:) captures its object strongly.

Thanks to it, my observable model now looks like this:

@Observable final class ObservableCalculator {

	var a: Int
	var b: Int
	private(set) var sum: Int

	private var cancellables: Set<AnyCancellable> = []

	init(a: Int = 0, b: Int = 0) {
		self.a = a
		self.b = b
		self.sum = a + b

		publisher(keyPath: \.a)
			.combineLatest(publisher(keyPath: \.b))
			.map(+)
			.assign(to: \.sum, onWeaklyCaptured: self)
			.store(in: &cancellables)
	}

}

It still needs Combine to work and uses the recursive call to withObservationTracking under the hood, and does not address the fact that continued observation is still required in the library.

Edit: Welp never mind I may have spoken too soon. It does not seem to work.

1 Like