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 View
s). 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>
andAlert.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 propertyrole
and replaces theAlert.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 AlertButton
s 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
needsIdentifiable
becausealert(item: )
requires its item to conform it.MultiButtonAlertType
needsEquatable
becauseonChange
which is used to catch transition ofBinding
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 functionalertContent
. 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 causeCannot 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!