Please consider this code:
import Combine
class TestViewModel: ObservableObject {
@Published public var value: Int?
var cancellable: AnyCancellable?
init() {
cancellable = Just(1)
.receive(on: DispatchQueue.main)
.assign(to: \.value, on: self)
}
}
As is when TestViewModel is created on the main thread self.value isn't assigned to until sometime after the init function exits. This means SwiftUI does two draws one for value == nil and one for value == 1.
Is there a way to make receive(on:) deliver the value immediately when called from the same scheduler (DispatchQueue.main in this case) instead of having it queued?
I've come up with this and it seems to do what I want:
extension Publisher {
public func receiveImmediatelyOnMain() -> AnyPublisher<Self.Output, Self.Failure> {
return self.flatMap({ value -> AnyPublisher<Self.Output, Self.Failure> in
if Thread.isMainThread {
return Just(value)
.setFailureType(to: Self.Failure.self)
.eraseToAnyPublisher()
} else {
return Just(value)
.setFailureType(to: Self.Failure.self)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
}).eraseToAnyPublisher()
}
}
Look good? Is there a better implementation out there somewhere?
Thanks,
Jesse
1 Like