How to display Alerts with different messages in SwiftUI in a simple and elegant way ?
While building a SwiftUI application, I had to find a way to display an Alert with custom messages depending on errors returned by my API reponse. It turns out this is not trivial as we can only have a single .alert() container in our ContentView. Here is a nice elegant way to achieve this.
If we look at the documentation, we observe that there are two ways to initialise an alert view :
- the first and most used using the 'isPresented' binding
.alert(isPresented: Binding<Bool>, content: () -> Alert)
- the second using the 'item' binding
.alert(item: Binding<Identifiable?>, content: (Identifiable) -> Alert)
Using the second way, we can create and display different alerts depending on a state variable of type Identifiable.
First, we have to create a struct of type Identifiable that will hold our different Alerts choices :
struct AlertID: Identifiable {
var id: AlertType
enum AlertType {
case .error1
case .error2
case .error3
}
}
We also create an optional state variable that will enable to trigger and show the required Alert.
@State private var alertId: AlertID?
Then, we create a builder method to build the Alert depending on our state variable.
private func alertBuilder(alertId: AlertID) -> Alert {
switch alertId.id {
case .error1:
return Alert(title: Text(“Error 1”))
case .error2:
return Alert(title: Text(“Error 2))
case .error3 :
return Alert(title: Text(“Error 3”))
}
}
Finally, we update our alert view holder to call the builder method and build the Alert depending on our alertID variable :
.alert(item: $alertId) {(alertId) -> Alert in
return createAlert(alertId: alertId)
}
And voilà ! We just have to change the state variable alertID with the value we want as following :
self.parent.alertId = AlertID(id: .otherError)
This will in turn trigger a refresh of the View, call the builder method and display our Alert to the user. We can even bind this state variable to another view in order to trigger the alert from it. This was very helpful to me to handle errors returned by my API and display them to the user.