Create Publisher For UIControl

Kiarash Vosough
Divar Mobile Engineering
4 min readJul 22, 2022

This article will teach you how to listen to UIControl’s events with combine’s publisher.

Introduction

Combine is a reactive framework developed by Apple, and it was released in IOS 13.

Unlike RxSwift, which has a separate library named RxCocoa to Provide Cocoa-specific capabilities for general iOS/macOS/watchOS & tvOS app development, Combine did not have such an extension. So it became a nightmare for developers to implement an interface to adopt a Combine’s stream for UIElement’s events.

This article will demonstrate that this nightmare was a misunderstanding and clarify that creating a custom publisher was never so easy.

I will not go through the details of Combine Elements, so the reader is assumed to have enough knowledge about reactive programming, specifically Combine Framework.

Publisher

So what are publishers? as apple said:

Declares that a type can transmit a sequence of values over time.

To start the process, we first need a publisher whose subscribers can send their requests and receive a subscription if possible.

  1. Create a struct (with a generic type C) that conforms to Publisher protocol.

The C will be used as the publisher's output, and for now, the Failure is set to Never. To reference the C and the event, they shall be received in the initializer and stored inside the struct. They are necessary to create a Subscription.

For the sake of not creating leaks, we can store the Control as a weak reference.

What does the receive do?

The received method acknowledges the subscribe request and returns a Subscription instance. The subscriber uses the subscription to demand elements from the publisher and can use it to cancel publishing.

So let us create a custom Subscription and then go back and complete the Publisher implementation.

Subscription

As Apple said:

A protocol representing the connection of a subscriber to a publisher.

The next step would be:

2. Create a class (with S and C generic type) that conforms to Subscription and implement the methods.

This stage depends on the control because the addTarget method should be used to register a selector and receive the events; also, the subscribers should be notified about the event, so storing a reference to Subscriber is mandatory too.

You can forget about storing control and its generic type, but you will be able to just send UIControl as an output(which is a parent class) and not the specific type of the control you are using.

On the handleEvent method, the subscribers should be notified about the event; it is done by calling receive method and passing it control as an argument.

As you may know, when a subscription is about to be disposed of DisposeBag, the cancel method is called, so it is obligatory to discard everything which was retained. Here the target is removed from the control(The safety actions were done before by declaring control as a weak reference).

Let us get back to the Publisher.

3. First, check whether the control still has value; if not, send completion to the subscriber, meaning that the stream is finished.

Then create an instance of InteractionSubscription and provide the subscriber with it. When the publisher receives a Subscriber, it will make a subscription and respond to the request.

4. Create a protocol that inherits from UIControl, and add this method:

A different protocol is used because the covariant Self can only appear at the top level of the method result type. So a protocol is used to address this limitation.

And All done, Was it tough to implement nearly 60 lines of code to adopt Combine Streams in UIKit?🧐

Certainly Not.

Usage

here is how to use the publisher. Easy peasy!😁

I hope you enjoyed it, and it comes in handy for those who argue about reinventing the wheel or such stuff:)))) sometimes reinventing stops us from adding a massive dependency to our project.

The complete implementation is available on my gist.

Have a lovely weekend😎😎.

--

--

Kiarash Vosough
Divar Mobile Engineering

iOS Developer and Swift Lover with over 5 years of experience on Apple platforms. Find me on Any Social Media by searching Kiarash Vosough:)