Skip to content

Instantly share code, notes, and snippets.

@simonbs
Created September 3, 2025 18:44
Show Gist options
  • Save simonbs/5c3716f9fd3a8a4ddae30c6dd8a95c73 to your computer and use it in GitHub Desktop.
Save simonbs/5c3716f9fd3a8a4ddae30c6dd8a95c73 to your computer and use it in GitHub Desktop.
SwiftUI view modifier for presenting an alert when an error binding has a value.
import SwiftUI
public extension View {
func alert<Message: View, Actions: View>(
_ title: LocalizedStringResource,
presenting error: Binding<Error?>,
@ViewBuilder message: @escaping (Error) -> Message,
@ViewBuilder actions: @escaping () -> Actions
) -> some View {
modifier(
ErrorAlertViewModifier(
title: title,
error: error,
actions: actions,
message: message
)
)
}
func alert<Message: View>(
_ title: LocalizedStringResource,
presenting error: Binding<Error?>,
@ViewBuilder message: @escaping (Error) -> Message
) -> some View {
modifier(
ErrorAlertViewModifier(title: title, error: error) {
Button(role: .cancel) {
error.wrappedValue = nil
} label: {
Text("OK")
}
} message: { error in
message(error)
}
)
}
}
private struct ErrorAlertViewModifier<Message: View, Actions: View>: ViewModifier {
let title: LocalizedStringResource
@Binding var error: Error?
@ViewBuilder let actions: () -> Actions
@ViewBuilder let message: (Error) -> Message
@State private var isAlertPresented = false
private var hasError: Bool {
error != nil
}
func body(content: Content) -> some View {
content
.alert(title, isPresented: $isAlertPresented) {
actions()
} message: {
if let error {
message(error)
}
}
.onChange(of: hasError) { _, newValue in
isAlertPresented = newValue
}
}
}
@simonbs
Copy link
Author

simonbs commented Sep 3, 2025

Example usage:

struct ContentView: View {
    @State var error: Error?

    var body: some View {
        VStack {
            Button {
                error = NSError(domain: "dk.simonbs.Example", code: -1, userInfo: [
                    NSLocalizedDescriptionKey: "This is an example error."
                ])
            } label: {
                Text("Trigger sample error")
            }
        }
        // 👇 The alert is presented when `error` has a value
        // and is automatically nil'd when the user closes the button.
        .alert("An error occurred", presenting: $error) { error in
            Text("Please try again later.\n\n\(error.localizedDescription)")
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment