swiftobservablecombine

How to get a publisher from a value, since the beauty of @Observable?


Following the Foo2 class example, I used to have my object as an ObservableObject, I could set a @Published value and listen to their changes the way I would do it with Combine.

Now that I am using the @Observable macro, shown on the Foo1 example, I can not create a Combine like pipeline.

Is there a way to listen to the @Observable macro values the way I used when using the @Published ones from an ObservableObject object?

@Observable class Foo1 {

  var isEnabled = false

  init() {
    isEnabled
      .map { $0 } // Error: Value of type 'Bool' has no member 'map'
  }
}

class Foo2: ObservableObject {

  @Published var isEnabled = false

  var cancellables = Set<AnyCancellable>()

  init() {
    $isEnabled
      .map { $0 } // Works like a charm
      .sink { print($0.description) }  
      .store(in: &cancellables)
  }
}

Solution

  • There is now an excellent library to restore publishing to an @Observable: https://github.com/NSFatalError/Publishable. Import the package, add @Publishable to your @Observable classes. Access the per-member publishers via the new .publisher var. This solution gives you all the best of @Observable and requires almost no changes to existing Combine pipelines based on @ObservableObject. Disclaimer: I am not the author of this package, just an admirer.