This is Understanding Combine, written by Matt Neuburg. It is a work in progress. Corrections and suggestions are greatly appreciated (you can comment here). So are donations; please consider keeping me going by funding this work at Or buy my books: the current editions are iOS 13 Programming Fundamentals with Swift and Programming iOS 13. Thank you!


By threaders I mean those operators that specify the thread (formally, the scheduler) on which messages should be sent. There are two of them: receive(on:) and subscribe(on:).

receive(on:) (Publishers.ReceiveOn) is by far the more commonly used. Basically, it ensures that the downstream part of the pipeline will receive values and other messages on a specified thread.

For example, a pipeline that starts with a data task publisher will nearly always include .receiveOn(DispatchQueue.main) somewhere in the pipeline. The reason is that you can’t guarantee that a data task publisher’s output will arrive on the main thread; in fact, it almost certainly won’t. But if you want to do something with that output, such as store it with .assign, you’ll probably need to do that on the main thread.

.subscribe(on:) (Publishers.SubscribeOn) works in the opposite direction: it affects the upstream-directed receive, request, and cancel messages used for subscribing, requesting values, and canceling.

Both methods take an optional options: parameter, but you are unlikely to use it.

Table of Contents