0

I have an old callback API, which has a newValue callback handler emitting one value at a time, and a completion callback, containing an Error or nil, if success.

Unfortunately, calling collecting blocks until the API sent all values!

func<T> collecting(newValue: @escaping (T) -> Void, completion: @escaping (Error?) -> Void) { ... }

func publisher<T>(_ type: T.Type) -> AnyPublisher<T, Error> {
    let subject = PassthroughSubject<T, Error>()
        
    collecting(newValue: { value: T -> Void in
        subject.send(value)
    } completionHandler: { error: Error? -> Void in
        if let error = error {
            subject.send(completion: .failure(error))
        } else {
            subject.send(completion: .finished)
        }
    }
    return subject.eraseToAnyPublisher()
}

This code above does not work, because calling collecting blocks, and the return statement is only called with finished.

How can you implement such API in Combine? I don't want to use any DispatchQueue.async, because scheduling should be handled by Combine.

mydefs
  • 172
  • 10

1 Answers1

0

wrap subject.send(value) with DispatchQueue.main.async

DispatchQueue.main.async {
    subject.send(value)
}

I am not able at this moment to explain why it worked for me.

Blazej SLEBODA
  • 8,936
  • 7
  • 53
  • 93