The Combine framework provides a declarative approach for how your app processes events. Rather than potentially implementing multiple delegate callbacks or completion handler closures, you can create a single processing chain for a given event source. Each part of the chain is a Combine operator that performs a distinct action on the elements received from the previous step.
Apple has integrated Combine’s API deep into the Foundation framework, so Timer, NotificationCenter and core frameworks like Core Data already speak its language. Luckily, Combine is also very easy to integrate into your own code.
Publishers are types that can emit values over time to one or more interested parties, such as subscribers.
An output value of the publisher’s generic Output type.
A successful completion.
A completion with an error of the publisher’s Failure type.
Operators are methods declared on the Publisher protocol that return either the same or a new publisher. That’s very useful because you can call a bunch of operators one after the other, effectively chaining them together.
Finally, you arrive at the end of the subscription chain: Every subscription ends with a subscriber. Subscribers generally do “something” with the emitted output or completion events.
When you add a subscriber at the end of a subscription, it “activates” the publisher all the way at the beginning of the chain. This is a curious but important detail to remember — publishers do not emit any values if there are no subscribers to potentially receive the output.
Even better, you don’t need to specifically memory manage a subscription, thanks to a protocol provided by Combine called Cancellable.
Combine is integrated on the system level. That means Combine itself uses language features that are not publicly available, offering you APIs that you couldn’t build yourself.
The “old” style async code via delegates, IBAction or closures pushes you towards writing custom code for each case of a button or a gesture you need to handle. That’s a lot of custom code to write tests for. Combine abstracts all async operations in your code as “operators”, which are already well tested.
When all of your asynchronous pieces of work use the same interface — Publisher — composition and reusability become extremely powerful.
Combine’s operators are highly composable. If you need to create a new one, that new operator will instantly plug-and-play with the rest of Combine.
Testing asynchronous code is usually more complex than testing synchronous code. With Combine, however, the asynchronous operators are already tested, and all that’s left for you to do is test your business logic — that is, provide some input and test if your subscription outputs the expected result.
Walking through this UML diagram:
The subscriber subscribes to the publisher.
The publisher creates a subscription and gives it to the subscriber.
The subscriber requests values.
The publisher sends values.
The publisher sends a completion.