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!


.handleEvents (Publishers.HandleEvents) is basically a completely generalized version of .print:

  • .print only does one thing: it prints. And it does it indiscriminately: it reports everything that passes through it.

  • .handleEvents does whatever you want it to; it consists of nothing but functions that you give it. And its behavior is separated out in accordance with what passed through it. It takes five functions, all of them optional; each function takes one parameter, except for cancel which takes no parameters:

    • receiveSubscription: — takes a Subscription

    • receiveOutput: — takes a value from upstream

    • receiveCompletion: — takes a completion (.failure or .finished)

    • receiveCancel:

    • receiveRequest: — takes a Demand

You can do whatever you like in whichever functions you supply, including printing to the console. Thus, for example, you might use .handleEvents to print out only Demands, so that you track the behavior of backpressure, or only cancel, so that you can watch the upstream flow of cancel messages after a downstream failure.

Although I have categorized .handleEvents as a debugger operator, it can also be used as a mid-pipeline equivalent of .sink.

WARNING: My experience is that under certain circumstance, .handleEvents can alter the behavior of the pipeline, thus causing you to draw erroneous conclusions about how the pipeline behaves. I regard this as a serious bug (a Heisenbug).

Table of Contents