If you have been playing around with Swift's Combine you probably reached a point where you need to create your own custom
Publisher. Besides the implementation details, I will do my best to share my thought process when doing it. A lot of help comes from the work done by Sergej Jaskiewicz at OpenCombine on Github. At most what I am doing in this post, is to share how you could do these implementations on your own, instead of digging through the OpenCombine repo.
Given that this is an experiment, if you spot a mistake, or have any feedback, let me know.
The first thing you need to understand with Combine, if you are coming from ReactiveSwift/ReactiveCocoa, is that operations (e.g.
map) are represented by an entity that encapsulates it. This approach means that if you are creating your own
func myOperation that works with other
Publishers you will also have to create a
Before jumping to the code, there are three main concepts, that we will use throughout these examples:
These three concepts are quite well definied and follow the Reactive-Stream spec, which I advise reading. You will see that I have skipped some of the steps, described in the spec. The goal of this post is besides implementing your custom
Publisher, for you to understand how these three entities work together.
Finally, I will also mention the concept of
Downstream when relevant. I followed Sergej's suggestion regarding naming, since they map well to my own mental model and most importantly how the data flows.
Let's start with the case when you want to create an entity, but without any operation. An example of such a case can be
Publisher, is initialized with a single value, that is sent once the subscription happens. In order to avoid conflicts with the original
Just provided by
Combine, let's call it
The significant bits are at line 16, 17. This is where we make a connection between our
MyJust and whatever subscriber that might be interested in its values.
At line 16, once you get a hold of the
Downstream, you specify how the
Subscription should work, by creating your own implementation with
MyJustSubscription. You pass the
Downstream and the actual
value at line 30.
At line 35 is where you define the
MyJust behaviour, by stating what should happen when something (or
Downstream) demands a value:
- You check that the demand is bigger than zero.
- You send the value via
- You complete the signal via
- You let go off the
Downstream, since the work is done.
Going back to line 17, you pass your custom subscription to the downstream via
subscriber.receive. In essence: the Subscriber, demands values from the Publisher, via a Subscription.
By now you migth be thinking: ok, so how do I demand a value?
sink can and will do the job:
In the next parts, we will further explore this concept. Any question hit me on twitter.