Reactive Programming in iOS with Combine

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

Part 1: Getting Started

03. Subscriber Operators and Subjects

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: 02. Publishers and Subscribers Next episode: 04. Challenge: Create a Blackjack Dealer

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.

Although you ignored them in the previous example, the sink operator actually provides two closures. One to handle receiving a completion event and one to handle receiving values. Let's jump back into some code to see that in action. Add this new example of using adjust publisher, which lets you create a publisher from any value. Using sink again, except this time implement both closures to handle receiving a completion event and a value and just print them out. Sink is one of two built-in operators you can use to subscribe to a publisher. The other is assign. The assign operator lets you set a received value, to a KVO compliant property of an object. Let's create a new example to check this out. Start by defining a some object type with a single value string property, along with a didSet property observer, to print out a new value when it's assigned. Then create an instance of some object. Now call publisher on an array of strings, to create a publisher that will send its values one by one. And then use assign to set each value as it's received to the value property of the object. Run the playground and sure enough your property is set to each new value received and print it in the didSet observer. So far you've learned about publishers and subscribers and how to work with them. It turns out there's another category of publishers that act as a go between, the imperative world and combined, called subjects. Subjects enable non combined imperative code, to send values to combine subscribers. And there's two kinds of them. PassthroughSubjects enable you to publish new values on demand. They'll happily pass along those values and a completion event. And then there's CurrentValueSubject. Which works just like PassthroughSubject except it hangs on to the most recent value. And you can get that value at any time via its value property. Now let's see how these subjects working code. Starting with PassthroughSubject. First, create an instance of a PassthroughSubject of string and never, and then a subscription to that subject that just prints out received values. This PassthroughSubject will emit string values and never emit an error. Remember that all publishers must declare the type of values and errors it can emit in advance. And subscribers must match those types to its input and failure types in order to subscribe to it. With the previous publishers you've created, these types were inferred. However, a PassthroughSubject is not initialized with starting values. So you have to explicitly declare the types. Continuing this example at two calls to the subject's send operator which allows you to send values on that subject to subscribers. Now we're on the playground and you'll see those strings, print it out. Next in a completion event on a subject using its send completion method, followed by sending another value. Will still there, actually be printed out though? Run the playground, and Nope. Once a subject completes, it's done. You can also send an error on a subject wrapped in a failure completion event. You'll learn all about doing that and handling those errors later on in the course. So that's PassthroughSubject. As I mentioned, CurrentValueSubject not only lets you send values to subscribers, it also lets you access the current value imperatively. Create a new example to see how this works. Very similar to the previous example, except you're using CurrentValueSubject this time. And it requires an initial value to be specified, an Int with value zero, in this case. The initial values type must match the type you specified for the CurrentValueSubject of course. Continue this example and first print out the subjects, current value, then send a couple new values and print the current value again. And finally send a completion event. Run the playground and you'll see the values printed as they're received in the subscription, and also when you explicitly printed the values. You can't tell which values are being received in the subscription and which are being imperatively printed though. You could distinguish them in the print statement but there's actually a better way to see what's going on. Combine has a print operator that will log all publishing events. Insert the print operator right before sink. And then run the playground again. Now it's much easier to see which values are being received versus imperatively being printed. Keep that print operator in your hip pocket. It's gonna come in handy a lot. In practice you'll often want to let subscribers subscribe to receive events from a publisher without being able to access additional details about that publisher. To accomplish that you can erase the type of the publisher. This is easier to understand with an example. So add this new one to your playground. Create a PassthroughSubject and then create an erased version of that subject by calling eraseToAnyPublisher. Option click on publisher. And you'll see that it's of type AnyPublisher Int Never. This type of erase version does not allow you to send values through it. Delete or comment out that line. And then finish all of this example by creating a subscription and printing out receive values, same as before. And then send a new value through the subject. Fantastic job. You've learned a lot in this chapter, and you'll put these new skills to work throughout the rest of the course and beyond. But not so fast, it's time to challenge yourself. So continue to the next episode where you'll create a blackjack card dealer using what you just learned.