Article in iOS App Development category.
Conquering ReactiveSwift: SignalProducer
Do you not know when to use Signal vs SignalProducer in your code? Our iOS team will teach you the best practices for using SignalProducer…
Welcome to part 4 of the Conquering ReactiveSwift series. In the previous article, we learned how to create and observe a signal. In this article, we will discuss when to use Signal vs SignalProducer, which is another important primitive under the category Source.
Definition of SingalProducer
As the name implies, SignalProducer is something that produces a Signal. Basically, a SignalProducer encapsulates a deferred and repeatable work which, when started, generates a Signal.
Well, how is it useful?
Remember, in our last article, we worked on the following problem statement.
How To Print a message of time elapsed on every five seconds interval for fifty seconds
We created a signal which emits an integer on every 5 seconds for next 50 seconds. Then we observed those integers and printed the time elapsed. Let’s suppose, now we want this to start on a button tap. However, as an observer, we can only observe the signal, we can’t make it start or stop. For this kind of scenario, a SignalProducer is a good fit.
So let’s get started! We will encapsulate the integer emitting code in a SignalProducer.
Here, A SignalProducer is initialized with a closure that is executed when the start method of the SignalProducer is invoked. This closure accepts an observer of type Signal.Observer<Int, NoError> and a lifetime of type Lifetime. The observer is used to send values. The lifetime gives us an opportunity to cancel ongoing work if the observation is stopped.
Now we have a SignalProducer ready. Let’s start and observe it.
Here we must keep in mind that, each invocation of a SignalProducer will produce different signals. The order and value of events received by observers of different invocation of a SignalProducer are different.
Suppose we want to interrupt the SignalProducer after 10 seconds. To do so, we have to dispose of it after 10 seconds.
According to our current implementation, the even though the observer is disposed of after 10 seconds, the SignalProducer keeps on emitting the integers for 50 seconds. While constructing a SignalProducer, we must keep in mind to free up resources and to stop ongoing tasks if it is interrupted, So let’s get it fixed.
We will check the hasEnded property of lifetime and send an interruption event as sendInterrupted.
Signal vs SignalProducer
To understand the difference between Signal vs SignalProducer, let’s take the analogy of TV and on-demand streaming service. Signal behaves like a TV feed which is a continuous stream of video and audio. At a given point of time, every observer of the TV feed sees the same sequence of the frame. The observer neither can inject any side effect to TV feed, nor it can start or stop the feed. The observer can only start and stop receiving the feed. On the other hand, SignalProducer is like an on-demand streaming service like Netflix. Here, the observer receives a stream of video and audio, but the sequence of the stream is different for a different observer. Here the observer can start, stop the feed.
Therefore Signals are generally used to represent event streams that are already “in progress,” like notifications, user input, etc. Whereas, SignalProducers are used to represent operations or tasks which need to be started. For example network requests, where each invocation of start will create a new underlying operation. In the case of Signal, the results might be sent before any observers are attached. In the case of SignalProducer, the results are not sent unless it is started.
I hope this article gave you an idea about when to use a Signal and when use a SignalProducer. You can find the sample code here. In the next article, we will discuss how to limit the scope of observation.