Alerts in SwiftUI
How to present Alerts in SwiftUI efficiently
I recently published my first app on the app store written in SwiftUI. During development, finding out how to create a single alert was very easy, with lots of resources online. However, once my application scaled up, I found that the common approach was unreliable when the cases of showing an alert grew.
This led me to write this article to go through the different approaches I have used, starting from a very simple alert to a more efficient approach that handles the different alert types, consecutive alerts, and child views presenting an alert.
Creating a Simple Alert
Creating an alert in SwiftUI can be done with a single @State variable of type Boolean and the .alert(isPresented) modifier. Whenever this variable gets set to true, the view will be reloaded and the alert will be presented. Once the alert is dismissed, Swift will handle setting the variable back to false.
Customising the alert
The content closure of the alert has to be of type alert
. These can vary in complexity. Alerts, by default, have a title and a dismiss button, but they can be customised to have a message and up to two buttons which can be tied to any functionality.
Some examples below:
Why this approach is not scalable
The above approach works well, but in practice, a view may need to show different alerts depending on the user's actions. In SwiftUI, a view can only have a single .alert
modifier attached to it.
A possible solution is to apply an alert modifier to each individual view element, but that brings inefficiency with duplicate code and multiple @State
variables, which become challenging to keep track of — especially if child views exist which also present alerts.
Introducing AlertItem
A better solution is to make use of the .alert(item)
modifier, which binds to an identifiable object and is presented whenever the identifiable item is not nil or is updated.
I like to use a custom struct which is similar to the SwiftUI alert struct and conforms to the Identifiable
protocol.
This allows an alert of varying complexity to be created on the fly when needed and doesn’t require multiple .alert
modifiers or @State
variables.
Then if you have child views that also present alerts, you can pass the AlertItem
as binding and be confident that the behavior should be no different.
Presenting an Alert Within an Alert
If you want to change the value of an AlertItem
within the action of another AlertItem
in the hope that it will dismiss the first alert and show the second one… it won’t.
This seems like a niche problem to meet; however, in an application, there may be an alert of the form:
Are you sure you want to <some action>?
If the user then confirms but the action fails, i.e loss of network connection, then it will be helpful to show another alert to say an error has occurred.
The solution is to update the value of the AlertItem
asynchronously. Once the action of the first alert has finished, the UI will be updated.
If you have any questions, post a comment below and if you would like to be notified when I next write an article join my newsletter below! 👇