Combine Pipeline vs Callback Pattern in iOS | by PTeng | Jun, 2022

Explained with example


In this article we will try to understand what a Combine pipeline looks like and how is it different from the traditional callback approach.

Ever since the Combine framework was introduced a few years ago by Apple starting iOS 13 many developers have adopted it their apps attracted by its ability to simplify complex processing steps in the form of so called pipelines.

We will work through a very simple set of examples (you can even run them in the Xcode playground !) where we try to accomplish the same task using the callback and the Combine approach.

We will try to implement a set of processing steps where we will fetch some employee data , apply a salary raise for the employees based on their department & finally generate a mailer that will print the final result of the processing.

We will implement this using the callback pattern and the Combine approach to visualise the difference.

Fetch Employees -> Apply salary raise -> Generate Mailer -> Print result

We will work with the below data structures that will represent the various data models that we are trying to work with and work towards.

We have the Employee , Department , EmployeeAddress & the Mailer data structures

To keep things simple we will create a set of data in code that will help us to keep the implementation simple and focus more on the concepts (In practice the data will likely come from a remote ReST API etc).

Below is the data for an Employee & EmployeeAddress data structure.

Fetch Employees

In the above example we have the fetchEmployees implemented as a “callback” & Combine function.

In the first approach the called function receives a callback function as an argument that will be invoked with the set of employees. The second function uses a Combine built in convenience publisher Justwhich helps to wrap any data and returns a Publisher.

The eraseToAnyPublisher function helps to type erase the publisher output so that it is easy to process the output by clients and allows us to change the underlying implementation of the publisher output.

This publisher Never returns an error so the <[Employee], Never> as the return type.

Apply Salary Raise

In the above functions, we loop through the Employee array and apply a salary raise. We invoke the callback or return a Publisher of type AnyPublisher<[Employee], Never> as before.

Generate Mailer

As a final step of our processing we need to generate a Mailer so that they can be sent to the next processing step (or just printed on the console in out case as we will see soon)

The above functions accept a set of Employee and then either call the callback with a set of Mailer objects or return a publisher.

We will now put the above individual implementations together to appreciate the difference !

As you can see, in the callback approach we need to nest the callbacks. You can imagine if the processing steps grow in the future the code will start to become complex to understand & maintain.

In the Combine approach, you can immediately see that the processing steps “chains “together to form a pipeline and is easy to reason and understand.

In the future if you were to ever need a new processing step (eg: Send email) you can easily introduce the step without having to necessarily increase the code complexity or needing a refactor.

flatMap is a Combine operator that transforms the elements from an upstream publisher into a new publisher.

sink is a built in subscriber that connects the publisher output to a closure (it usually ends a pipeline).

Note: It should be noted that to form a pipeline the output of the first publisher should match the input expected by the next publisher in the pipeline. So in our case fetchEmployee returns a Publisher of type AnyPublisher<[Employee], Never & applyRaise expects an array or Employee .

The complete example can be found here.

For those wanting to understand the concepts, Combine docs from Apple are an excellent source of documentation. It is useful to grasp some key concepts such as Publishers, Subject & Subscriber to start, followed by built in publishers (such as Just, Future & Empty among others) , subscribers such as sink and last but not the least Combine operators (such as flatMap, tryMap, zip, collect among a huge list of others)

News Credit

%d bloggers like this: