RxSwift and Alerts

Jim Campagno
BetterPT engineering
6 min readOct 11, 2017

This blog post will cover how you can create a custom alert in your iOS app using RxSwift.

The following are two screenshots of our application, and the alert (upcoming appointment) we will be going over which you can see at the bottom of the screen:

The users of our app can be referred to as patients. The reason why they’re downloading our app is to book an appointment with a specific physical therapist at a clinic in their area. We intend on making this process very easy for them. After the user books an appointment, we will bring them back to the home-screen (first screen of the app which you can see above) to then present them with an alert which provides details of their upcoming appointment.

If a user was to tap that upcoming appointment alert (from the home-screen), they would be provided with additional details of the appointment, which you can see in the following screenshots:

One of the first things I like to do when creating any custom type (or view) that will be used throughout the application is to create a mental checklist:

  • It should be easy to use by other developers
  • It should not be constrained to work only for the specific task at hand
  • Map through how this type will be used by the user in all its scenarios before putting pen to paper (fingers to keyboard)

Scoping out how to do this, first we should implement a UIView that can come up from the bottom of the screen, keeping in mind how the users of this type (your other developers along with yourself) will be using this type. Organizing your code from the start, stepping back to clean up unused code after you've immediately implemented something is crucial.

The type we will be creating is BottomAlert. And we will be stepping through how we implemented this type to take full advantage of RxSwift. The following three methods are the only methods exposed to the developers to use on this type:

I will be explaining these methods shortly. I want you to first see what this winds up looking like, stepping through it to see if you figure out how we would wind up interacting with it.

The BottomAlert type (which is of type UIView), will have the following stored and computed properties. Note that it's hooked up to a .xib file. The white bar with a shadow is a UIImage within the cardImageView (which is a UIImageView).

You should notice that there are also type properties, one stored property makes reference to an instance of BottomAlert (a singleton). But we don't allow outside access to any of these properties as they will be only used internally within the BottomAlert declaration.

The idea is that we will then create various type methods (which you can see above) that will in turn create an instance of a custom UIView that will represent the type of alert we're looking to show to the user. That custom UIView will itself have a property that will be an Observable which will be returned back to the caller of the function. The reason for this is that the custom UIView will lay itself out accordingly and any taps that occur that then require an action will be passed through the Observable.

Lets take a look at one of these custom UIViews.

Looking through this code, as to how the user will interact with it is through a tap. A tap on anywhere on the view itself, will in turn call onNext() on the publishSubject. Our publishSubject stored property is set to fileprivate. This ensures that the only one who can interact with it is the UpcomingAppointmentView type where we won't receive any false information when we ultimately subscribe to the Observable.

This is really powerful and simplifies the entire process. We don’t have a delegate property that needs to be assigned a value that we would then communicate through. Instead, right at the call site (which you will see shortly), we can write the necessary code to what we would like to have happen as a result of the tap because we will be subscribing to this observable.

Here is how we call the BottomAlert. There's no requirement to adopt/conform to a protocol to then create an instance of BottomAlert. This allows it to be easily used throughout anywhere in our code base, at any time. Note that in the following example, text is a variable of type String and view is a variable of type UIView I have access to.

In our UIViewController that is first displayed to the user, in viewDidLoad() we make a network request looking to see if our logged in user has an upcoming appointment at a clinic. If they do, then we call through to the displayUpcomingAppointment(text:view:) on the BottomAlert type which will return back to us an Observable<Void> which we are subscribing to. When a tap occurs, it will call through to the publishSubject which we would be subscribed to (in the code above). In the onNext block of code is where we will then present a new UIViewController which will display details of the upcoming appointment.

This methodology is easier to understand, cleaner and couples the reaction to an action taken by the user in one place as opposed to going through the delegate pattern which would have separated things.

The following is using this same methodology in a more complicated situation. When a user has gone through with finishing an appointment, if they were to then visit the UIViewController which displays to them their current and past appointments, we will bring up an alert asking them to rate the clinic. This alert isn't just going to handle a tap, there are different taps that can occur within the alert that require separate actions, like so:

This alert utilizes a different UIView type which we've called ReviewYourLastAppointmentView which handles the situations pointed out above with an enum and a different publish subject:

When our AppointmentViewController presents itself, we will make a network request to determine if we even need to bring up the alert to have the user make a decision. If we want to display the alert on this view controller, this is what that code would look:

And here is what our handleOnNext(result:) method looks like which is part of the AppointmentViewController which presented this alert:

Using RxSwift is really great at centralizing the various conversations we need to have occur between the UIViewController presenting the BottomAlert and the various actions that can occur from the custom UIView within the BottomAlert. The custom UIView created within the BottomAlert is decided by the static type method called through on the BottomAlert. Anywhere in our code base, we can utilize this alert and react accordingly. There's no need to setup any delegate pattern in responding to what might occur. Setting it up this way also allows us to easily expand on the type without breaking the code anywhere else.

I want to conclude by stating that there are places in this code where we can take full advantage of RxCocoa which would make these types even easier to use. In a future blog post, I will break down exactly how we can refactor this to take full advantage of RxCocoa.

Originally published at gist.github.com.

--

--