SwiftUI | Make Alert Management Easier with Protocol

Enebin
4 min readSep 12, 2022

--

Photo by Sigmund on Unsplash

Goals

While implementing alert with native SwiftUI features, there’re things that always bother me.

Boring repetitive jobs

Creating a new Alert requires passing multiple pieces of content: buttons, title, and message. Even for message, I must pass them in the form of a view struct Text, not a String. It’s really annoying. I want to get this handled automatically.

Too many variables to consider

I have to manage a variable isPresented along with the actual content for the alert window(Alert or any Views). What if I forgot to set alert’s content to a new value? It’s quite error prone.

Alert I’m using will be obsolete in the future

Since iOS 15, alert get changed to use SwiftUI’s Button instead of Alert we used until iOS 14. Looks like I must refactor the old one someday. But I want to avoid boring, painful jobs as much as possible.

That seems to be enough motivation to improve our alert. Then let’s dive in!

Set protocol BaseAlertType

Alert has three configurable components; title, message, button. So let’s begin with defining a protocol BaseAlertType. It means the protocol that all alerts must follow.

There’s an unfamiliar element, AlertButton. Let's take a closer look at it.

AlertButton

AlertButton is kind of a common blueprint I made for the buttons used in alert.

A button in alert window needs label, role, action.

  • Label is the content of button like “Cancel”, “Ok” from the above image.
  • Role determines appearance of the button and window. If you choose a role destructive, its texts become red and bold.
  • Action is literally an action that is executed when tapping the button.

Since Button<Text> and Alert.Button have slightly different ways of creating buttons with roles, we need to create another blueprint for common roles. AlertButtonRole.

AlertButtonRole

  • Button in iOS 15 has a new property role and replaces the Alert.Button from the old one.
  • This enum will be used later to create each buttons.

Convert to system button

Now we have a mission to convert those AlertButtons to actual buttons like Alert.Button or Button of SwiftUI. Let’s look into the codes.

Almost done! Only thing left is making an actual alert from the ingredients we’ve got.

Subprotocol

What you need know is alert is changed quite a lot since iOS 15. For the details, please check out the official document. In this post, we’ll just focus on how to deal with those differences.

I separated the protocol in two parts depending on the version of iOS and named them AlertType and MultiButtonAlertType respectively.

You can see the protocols need additional conformance of other protocols. This is because they’re used differently in each version of view.

  • AlertType needs Identifiable because alert(item: ) requires its item to conform it.
  • MultiButtonAlertType needs Equatable because onChange which is used to catch transition of Binding requires its item to conform it.

Make a view

All that remains is just fill in parameters for alert.

  • In the presenting parameter, there’s a function alertContent. It’s a computed variable I made for the ease of conversion. If you’re wondering about it, check out the codes in my repository(alertView, alertContent).
  • One thing tricky is to handle optional value. Returning nil from the warning is not possible, so I chose to unwrap it to default values. There must be a better way that I couldn’t find. It would be appreciated if you tell me about a better solution 🤣

Make a View extension

  • Declare a method that returns the view struct you created earlier in your View extension. Now you can use it anywhere a view exists.

Usage

Now you are ready to use showAlert in your project. Here’s an example.

  • The most attractive thing here is that it’s no longer affected by the iOS version.
  • When passing buttons, you can simplify it to only pass an array of buttons. It’s very convenient because you don’t care about the number of buttons, whether it’s one, two, or more. Just deliver as many as you need. Here’s how I did it. — Github AlertType, MultiButtonAlertType
  • One thing you should keep in mind is to define the alertState variable optional. It will cause Cannot convert value of type error when it’s not optional.

More examples are in here and more will be update later.

About Apple’s alert window policy

Before you leave, there’re something you must know about Apple’s alert policy. It’s about role of buttons that might affect the appearance of alert windows. You can get some detailed explanation in the other post I wrote.

Try it!

This project is distributed through SPM. You can download the codes directly from Github, or if it bothers you, you can install it through SPM. Contributions are also very welcome if you want.

Thank’s for reading!

--

--

Enebin
Enebin

Written by Enebin

Making your dreams a reality |  Mainly Interested in iOS | https://github.com/enebin

No responses yet