https://unsplash.com/photos/text-on-white-textile-ZwI6tCPxOy4

SwiftUI Reusable Alert

Gagan Vishal Mishra
3 min readNov 6, 2024

Problem:

While developing an app in SwiftUI, I added duplicate code for displaying alert message on Views, And this is not good practice.

Later I was looking for same approach as we do in UIKit + Swift by adding UIViewController’s extension and add Alert there. We have achieved in previous story Link

So keeping in mind, To create a reusable alert class in SwiftUI that can be used throughout your app, you can define a AlertManager class.

Create the AlertManager Class

import SwiftUI
import Combine

@Observable
class AlertManager {
static let shared = AlertManager()

var isShowingAlert = false
var alertTitle = ""
var alertMessage = ""
// Property to store multiple buttons
@Published var alertButtons: [Alert.Button] = []

// MARK: - Make the initializer private to enforce the singleton pattern
private init() {}

func showAlert(alertTitle: String, alertMessage: String, alertButtons: [Alert.Button]) {
self.alertTitle = alertTitle
self.alertMessage = alertMessage
self.alertButtons = alertButtons
self.isShowingAlert = true
}

func dismissAlert() {
self.isShowingAlert = false
self.alertButtons = [] // Reset buttons after dismissing
}
}

AlertManager is a singleton class (shared instance) so you can access it globally across the app.

uses @Observable macro to notify views when the alert should be shown or hidden.

Create an Alert Modifier for SwiftUI Views

Create a custom modifier to make it easier to attach an alert to any view

struct AlertModifier: ViewModifier {
@State var alertManager = AlertManager.shared

func body(content: Content) -> some View {
content
.alert(isPresented: $alertManager.isShowingAlert) {
if alertManager.alertButtons.count == 2 { // In case we have two buttons e.g. Accept & Decline
return Alert(
title: Text(alertManager.alertTitle),
message: Text(alertManager.alertMessage),
primaryButton: alertManager.alertButtons[0],
secondaryButton: alertManager.alertButtons[1]
)
} else if alertManager.alertButtons.count == 1 { // In case we have only one custom button e.g. Accept
return Alert(
title: Text(alertManager.alertTitle),
message: Text(alertManager.alertMessage),
dismissButton: alertManager.alertButtons[0]
)
} else { // In case we have only one default button with title 'OK'. e.g. no internet message
return Alert(
title: Text(alertManager.alertTitle),
message: Text(alertManager.alertMessage),
dismissButton: .default(Text("OK")) {
alertManager.dismissAlert()
}
)
}
}
}
}

Create an extension of View

extension View {
func globalAlert() -> some View {
self.modifier(AlertModifier())
}
}

How To Use

In your view

struct ToDoView: View {
var body: some View {
VStack {
Button("Two Button Alert With Action") {
towButtonAlertWithAction()
}
.padding()

Button("Single Button Alert With Action") {
singleButtonAlertWithAction()
}
.padding()

Button("Single Button Alert NO Action") {
singleButtonAlertNoAction()
}
.padding()
}
.globalAlert() // Attach the global alert modifier
}
}

private extension ToDoView {
func towButtonAlertWithAction() {
AlertManager.shared.showAlert(
alertTitle: "Action Alert",
alertMessage: "This alert has two buttons with actions.",
alertButtons: [
.default(Text("Accept")) {
print("Accept tapped")
},
.cancel(Text("Decline").) {
print("Decline tapped")
}
]
)
}

func singleButtonAlertWithAction() {
AlertManager.shared.showAlert(
alertTitle: "Action Alert",
alertMessage: "This alert has single button with action.",
alertButtons: [
.default(Text("Accept")) {
print("Accept tapped")
}
]
)
}

func singleButtonAlertNoAction() {
AlertManager.shared.showAlert(
alertTitle: "Alert",
alertMessage: "This alert has single OK button with no action.",
alertButtons: []
)
}
}

Now when we tap on Single button alert we have

We have made it. 🎉

Feel free to add your suggestion please or if you have better approach to achieve it.

Sign up to discover human stories that deepen your understanding of the world.

Gagan Vishal Mishra
Gagan Vishal Mishra

Written by Gagan Vishal Mishra

Experienced Sr iOS and mobile app developer. Love to solve customer problem in the easiest and quickest way.

No responses yet

Write a response