Reactive Programming in iOS with Combine

Feb 4 2021 · Swift 5.3, macOS 11.0, Xcode 12.2

Part 1: Getting Started

02. Publishers and Subscribers

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 01. Introduction Next episode: 03. Subscriber Operators and Subjects

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

Now that you've learned some of the basic concepts of combine, it's time to jump in and learn about two of combine's core components, publishers and subscribers. At the heart of combined is the publisher, it publishes or emits events that can include values of interests. If you've developed on Apple platforms before, you can think of a publisher as kind of like notification center. What observes a publisher and combined is referred to as a subscriber. It attaches to or subscribes to a publisher, imagine that, and it can then receive the values and events the publisher emits. The whole process goes like this, a subscriber indicates that it wants to subscribe to a publisher, the publisher then issues as subscription to the subscriber. Now the subscriber can request values from the publisher, and the publisher can oblige by sending values to the subscriber. A publisher can continue to send values until it sends a completion event to the subscriber to indicate that it won't send any more values. This is called a marble diagram, and the vertical bar represents a normal unfinished completion event. A publisher can also complete with a failure event which has shown as a red X in the marble diagram. Just remember that once a publisher emits a completion event it's done, and can no longer emit any more values or another completion event. The requirements of a publisher and subscriber are defined in protocols. Here's the Publisher protocol, and one of its most crucial extensions. The Publisher protocol defines an output, associated type for the types of values a publisher will produce, and an associated type for the type of error, it may emit or never if it's guaranteed to never emit an error. A subscriber calls, subscribe on a publisher to attach to it. And the implementation of subscribe will call receive subscriber to actually create the subscription. Notice that subscribe and receive must line up the subscriber output and error types, so that it takes care of the publisher. Now let's take a look at the Subscriber protocol. It defines an input associated type for the type of values the subscriber will receive, and this type must match the output from the publisher. It also defines a failure type or never, if there can be errors just like in the Publisher protocol. If there is a failure type, it must match the publishers failure type. The publisher calls receive subscription on the subscriber to give it the subscription. And the publisher calls receive on the subscriber to send it a new value. When it's done the publisher calls received completion on the subscriber to tell it that it has finished producing values either normally or due to an error. The curious of you may be wondering about that CustomCombineIdentifierConvertible. This is just a protocol that defines a combined identifier requirement which is used to uniquely identify each publisher stream along with the default implementation. There's one more protocol to take a look at, for now don't worry, it's a short one. The Subscription protocol defines the connection between the publisher and the subscriber. A subscriber calls request to indicate it's willing to receive more values up to a max number, or it can specify that it's willing to receive an unlimited number of values. This concept of a subscriber stating how many values it's willing to receive is known as backpressure management. Without it a subscriber could get flooded with more values from the publisher than it can handle, and this can lead to problems. You'll learn more about managing backpressure in a later episode. So what's up with that Cancellable in the protocol definition? Cancellable defines just a single method cancel, subscriptions return a cancellable type as a cancellation token, and can manually call cancel on it to cancel the subscription. That's a lot to take in, so no worries of all of this doesn't make total sense just yet, it soon will. How about jumping into some code? Here in the beginning playground for this episode, there are two things, I'd already defined for you, a subscription set, this is where you'll store your subscriptions. Notice that it's a set of AnyCancellable. AnyCancellable is just a concrete implementation of the Cancellable protocol. You learned a moment ago that you can manually call cancel on a subscription to cancel it. However, you can also add these tokens to a collection, and they'll be automatically canceled when that collection is about to be deallocated. There's one more thing I wanna show you before you get to writing some code. Open Sources in the Project navigator and select SupportCode.swift, it contains a helper function example(of:). You'll use this function to wrap each example you'll code throughout this course. Okay, back to the main playground page. I mentioned earlier that you can think of a publisher as kind of like notification center, actually notification center has a combined method that can broadcast notifications. To see this in action add a new example to your playground. First, you get a handle to default notification center, then create a notification name and a publisher for your notification. Option-click on publisher(for:object:), and you'll see that it returns a publisher that emits an event when the notification center broadcast a notification. So what's the point of publishing notifications when a notification center is already capable of broadcasting its own notifications without a publisher? Glad you asked, you can think of these types of methods as a bridge from the old to the new, a way to Combine-ify, existing APIs, such as notification center. Okay, let's finish off this example. First create a subscription to the publisher then post a notification and finally cancel the subscription. Run the playground and you'll see the following. You created a subscription by calling sink on the publisher but don't let the obscurity of that method name give you a sinking feeling. Option-click on Sink and you'll see that it simply provides an easy way to attach a subscriber with closures to handle the output of a publisher. In this example, you ignore those closures and then say just print a message to indicate that a notification was received. Remember that handsome graphic at the beginning of this video that showed all that back and forth between a publisher and a subscriber? Want to see that interplay in your actual code? Of course you do, and it's super easy to do. Just insert the print operator right before the sink. Remember that operators are just methods declared on a publisher. Rerun the playground and check it out. Print logs, every publishing event so you can see exactly what's going on. The subscription is created and received by the subscriber, it requests unlimited values, it receives the notification and prints out the message, and then the subscription is canceled. Pretty cool, right? So about that unlimited bit, the sink operator will continue to receive as many values as the publisher emits. This is known as unlimited demand, which we'll learn more about shortly.