Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a Publisher from a callback

Tags:

swift

combine

I would like to wrap a simple callback so that it would be able to be used as a Combine Publisher. Specifically the NSPersistentContainer.loadPersistentStore callback so I can publish when the container is ready to go.

func createPersistentContainer(name: String) -> AnyPublisher<NSPersistentContainer, Error> {
  // What goes here?
  // Happy path: send output NSPersistentContainer; send completion.
  // Not happy path: send failure Error; send completion.
}

For instance, what would the internals of a function, createPersistentContainer given above, look like to enable me to do something like this in my AppDelegate.

final class AppDelegate: UIResponder, UIApplicationDelegate {

  let container = createPersistentContainer(name: "DeadlyBattery")
    .assertNoFailure()
    .eraseToAnyPublisher()

  // ...

}

Mostly this boils down to, how do you wrap a callback in a Publisher?

like image 956
Ryan Avatar asked Jul 10 '26 10:07

Ryan


1 Answers

As one of the previous posters @Ryan pointed out, the solution is to use the Future publisher.

The problem of using only the Future, though, is that it is eager, which means that it starts executing its promise closure at the moment of creation, not when it is subscribed to. The answer to that challenge is to wrap it in the Deferred publisher:

func createPersistentContainer(name: String) -> AnyPublisher<NSPersistentContainer, Error> {
    return Deferred {
        Future<NSPersistentContainer, Error> { promise in
            let container = NSPersistentContainer(name: name)
            container.loadPersistentStores { _, error in
                if let error = error {
                    promise(.failure(error))
                } else {
                    promise(.success(container))
                }
            }
        }
    }.eraseToAnyPublisher()
}
like image 77
Matej Balantič Avatar answered Jul 14 '26 19:07

Matej Balantič



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!