This is Understanding Combine, written by Matt Neuburg. Corrections and suggestions are greatly appreciated (you can comment here). So are donations; please consider keeping me going by funding this work at http://www.paypal.me/mattneub. Or buy my books: the current (and final) editions are iOS 15 Programming Fundamentals with Swift and Programming iOS 14. Thank you!
Two extremely simple operators manage situations involving no values.
.ignoreOutput
(Publishers.IgnoreOutput) ensures that the downstream has no values. It is the ultimate blocker; it just swallows all the incoming values and doesn’t output anything. Its output type is the same as the output type of the upstream, but in fact it will never emit a value of that type. It merely passes along the completion it receives from upstream.
.replaceEmpty
(Publishers.ReplaceEmpty) deals with an upstream that has no values. It is the opposite of .ignoreOutput
: it transforms nothingness into somethingness. This operator is initialized with a single value of the upstream Output type, which it stores. If a value or an error comes down the pipeline, this operator passes it on down the pipeline, and never does anything else. But if a .finished
completion comes down the pipeline, without a value or an error having come down the pipeline previously, this operator passes its stored value down the pipeline, and then sends a .finished
completion.
In this way, a pipeline that does nothing is made to do something. For example, suppose we’re subscribed to a stream of Ints, but the upstream might finish without ever providing us with an Int. And suppose we’d like to signal that as a value. We might decide to convert all incoming Ints into Optional Ints; that way, we can signal nil
to mean there were no values:
myPublisher
.map(Optional.init)
.replaceEmpty(with:nil)