DispatchQueue.main VS RunLoop.main: Main difference |Combine
Scheduler:
The Combine framework provides the Scheduler
protocol, which is a powerful abstraction for describing how and when units of work are executed. We can use a scheduler to execute code as soon as possible, or after a future date. It provides many disparate ways of executing work, such as DispatchQueue
, RunLoop
and OperationQueue
.
Let’s consider the example below,
private var subscriptions = Set<AnyCancellable>()
func fetchMovies(from endpoint: Endpoint) -> Future<[Movie], MovieStoreAPIError> {
return Future<[Movie], MovieStoreAPIError> {[unowned self] promise
//...// Schedule to receive the sink closure on the
// main dispatch queue.
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { (completion) in
// ...
}, receiveValue: { promise(.success($0.results)) })
.store(in: &self.subscriptions)
}
}
As we can see in the above code example, we’re making sure to receive the movies on the main thread using the DispatchQueue.main scheduler. The main queue scheduler is required since we need to perform UI updates on the main thread.
What is DispatchQueue.main?
It is the dispatch queue associated with the main thread of the current process. The system automatically creates the main queue and associates it with your application’s main thread. Tasks are being executed serially or concurrently by dispatch queue on its associated thread.
What is RunLoop.main?
A RunLoop
object processes input for sources, such as mouse and keyboard events from the window system and Port
objects or touch events from an application. A RunLoop
object also processes Timer
events.
Your application neither creates nor explicitly manages RunLoop
objects. The system creates a RunLoop
object as needed for each Thread
object. The system is also responsible for creating the main run loop representing the main thread.
RunLoop.main and DispatchQueue.main are the similar but different:
From above definition's ,both RunLoop.main and DispatchQueue.main execute their code on the main thread, meaning that you can use both for updating the user interface. Both schedulers allow us to update the UI after a Combine value was published, which is why there’s no apparent reason stopping us from using one or another. Though, there are some essential differences to know.
The differences between RunLoop.main and DispatchQueue.main:
The main difference between RunLoop.main and DispatchQueue.main is that execution of code. DispatchQueue.main execute code directly where as RunLoop may be busy. RunLoop.main scheduler is executed using perform selector while in case of DispatchQueue.main is executed using gcd method.
RunLoop.main will give callback only when it is working in default mode and it is not the case always when user is interacting with the device or performing some actions. for example, suppose you are downloading image from the API while scrolling the table view using RunLoop.main as a scheduler then your image wont be shown on your view screen until you stop interacting with the screen. Because you have used RunLoop as a scheduler and it is busy in handling user interaction, So in this case we should always use DispatchQueue.main as a scheduler.
When should I use RunLoop.main as a scheduler:
Updating the UI while scrolling might affect the performance and smooth scrolling. In that case where your UI update isn’t as necessary when the user is scrolling, then it might make sense to use RunLoop.main as a scheduler.
Useful Links 👇🏼
https://github.com/apple/swift/blob/b... https://github.com/apple/swift/blob/2...