I can specify the scheduler as RunLoop.main
, but I could not find a native way to provide the associated RunLoop.Mode
mode to receive elements from a publisher.
Why do I need this: I'm updating a tableView cell from my publisher but the UI does not update if the user is scrolling, it then updates as soon as the user interaction or scroll stops. This is a known behaviour for scrollViews but I want my content to be displayed as soon as possible, and being able to specify the run loop tracking mode would fix this.
Combine API: I do not think the receive(on:options:)
method have any matching options to provide this. I think internally, if I call receive(on:RunLoop.main)
then RunLoop.main.perform { }
is called. This perform method can take the mode as parameter but this is not exposed to the Combine API.
Current Idea: To go around this I could do the perform action myself and not use the Combine API, so instead of doing this:
cancellable = stringFuture.receive(on: RunLoop.main) // I cannot specify the mode here
.sink { string in
cell.textLabel.text = string
}
I could do this:
cancellable = stringFuture.sink { string in
RunLoop.main.perform(inModes: [RunLoop.Mode.common]) { // I can specify it here
cell.textLabel.text = string
}
}
But this is not ideal.
Ideal Solution: I was wondering how could I wrap this into my own implementation of a publisher function to have something like this:
cancellable = stringFuture.receive(on: RunLoop.main, inMode: RunLoop.Mode.common)
.sink { string in
cell.textLabel.text = string
}
Were the API of this function could be something like this:
extension Publisher {
public func receive(on runLoop: RunLoop, inMode: RunLoop.Mode) -> AnyPublisher<Future.Output, Future.Failure> {
// How to implement this?
}
}