Sobes.tech
Junior — Middle

Why and how to use DispatchQueue.main.async when working with Combine in your app?

sobes.tech AI

Answer from AI

In Combine, subscribers can receive events on different threads depending on where the data is published. However, UI updates in iOS must occur only on the main thread. If you try to update the interface from a background thread, the app may behave incorrectly or even crash.

Using DispatchQueue.main.async guarantees that the code inside the block executes exactly on the main thread. In the context of Combine, this is often necessary when you receive data in the background and want to update the UI:

somePublisher
    .receive(on: DispatchQueue.main) // or
    .sink { value in
        DispatchQueue.main.async {
            // update UI
            self.label.text = "\(value)"
        }
    }
    .store(in: &cancellables)

Often, instead of explicitly calling DispatchQueue.main.async, the operator .receive(on: DispatchQueue.main) is used, which switches the execution thread for subsequent operators and subscribers.

Thus, DispatchQueue.main.async is needed for safe UI updates from Combine streams that may work in the background.