Functional Reactive Programming using Combine framework
Functional Reactive Programming (FRP) languages allow you to process values over time and allow you to deal with asynchronous code. In iOS, the Combine framework allows you to write functional reactive code by providing a declarative Swift API. Combine framework is an alternative to popular frameworks like RxSwift and ReactiveSwift.
Combine has some core concepts that need to be understood.
- Publisher and Subscriber
- Subjects
- Operators
Publisher and Subscriber
Publisher exposes values that can change on which a subscriber subscribes to receive all those updates. Publisher is a protocol which has two associated type first one is Output which is the kind of value reproduced by publisher and second one is Failure which is the kind of error produced by publisher. Publishers have one key function which is called subscribe. This function needs subscriber input as a parameter to match with the publisher’s output.
Subscriber is responsible for requesting data and accepting the data (and possible failures) provided by a publisher. A subscriber is described with two associated types, one for Input and one for Failure. The subscriber initiates the request for data, and controls the amount of data it receives. A subscriber receives a stream of value, completion or failure events from a publisher. There are two built-in subscribers in Combine i.e. sink and assign. Both Assign and Sink conform to the cancellable protocol.
Rules of a subscription
- A subscriber can only have one subscription
- Zero or more values can be published
- At most one completion will be called
Subject
Subject is also a type of publisher on which we can subscribe but also dynamically send events to them. Subject exposes a method for outside callers to publish elements.
There are two types of built-in subjects with Combine: PassthroughSubject, CurrentValueSubject.
PassthroughSubject
If you subscribe to it you will get all the events that will happen after you subscribed. When it is created, only the types are defined. When a subscriber is connected and requests data, it will not receive any values until a .send() call is invoked. PassthroughSubject does not maintain any state, it only passes through provided values.
CurrentValueSubject
CurrentValueSubject remembers the current value so that when a subscriber is attached, it immediately receives the current value. When a subscriber is connected and requests data, the initial value is sent. Further calls to .send() afterwards will then pass through values to any subscribers. When it is created currentValueSubject, you do so with an initial value of the relevant output type for the Subject.
Operators
Operators are a convenient name for a number of pre-built functions that are included under Publisher. This describes when and where a particular event is delivered. This is supported by runloop and dispatch queue. The operators can be divided in 5 macro categories, based on how they manipulate the data.
- Transforming Operators: Collect, Map, FlatMap, FlatMap, ReplaceEmpty, Scan.
- Filtering Operators: Filter, CompactMap, IgnoreOutput, First, Last, DropFirst, Drop, Prefix.
- Combining Operators: Prepend, Append, SwitchToLatest, Merge, CombineLatest, Zip.
- Time Manipulating Operators: Delay, Collect by time, Debounce, Throttle, MeasureInterval.
- Sequence Operators: Min, Max, First, Last, Output, Count, Contains, AllSatisfy, Reduce.
Example: Data task with combine framework
The Foundation framework contains a lot of extensions to work with Combine. So the most common example is usually the following one.
- First we make a cancellable storage for your Publisher
- Then we create a brand new data task publisher object
- Map the response, we only care about the data part (ignore errors)
- Decode the content of the data using a JSONDecoder
- Erase the underlying complexity to a simple AnyPublisher
- Use sink to display some info about the final value
Benefits of using the Combine framework
@Published usage to bind values to changes
This keyword is a property wrapper and adds a Publisher to any property. A simple example can be a boolean which we assign to the enabled state of a UIButton.
Combine with MVVM
The Combine framework is perfectly suitable to work in combination with MVVM. Here is an example.
Timer
You can use Combine to get periodic time updates through a publisher
NotificationCenter
You can also subscribe to notifications by using publishers.
Conclusion
In this article, we discussed the Combine framework in swift and Functional Reactive Programming. Also, we look at some benefits of using Combine in reactive programming with some code.
Combine examples, visit our repository on GitHub:
https://github.com/Mahesh471/Combine.git