Skip to content

Instantly share code, notes, and snippets.

@cdf1982
Created April 24, 2024 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdf1982/9dafe67228e359a7752cf985edb8f7b8 to your computer and use it in GitHub Desktop.
Save cdf1982/9dafe67228e359a7752cf985edb8f7b8 to your computer and use it in GitHub Desktop.
Hopefully a more convenient method to present Alerts in SwiftUI at runtime
//
// CustomSwiftUIAlert.swift
// Field
//
// Created by Cesare Forelli on 24/04/24.
//
import SwiftUI
/// ## Bindable object to be presented at runtime in a SwiftUI Alert
///
/// Whenever a `CustomSwiftUIAlert` @State variable has a value, SwiftUI automatically presents an Alert via the the provided custom view modifier:
///
///```swift
/// .alert(with customSwiftUIAlert: Binding<CustomSwiftUIAlert?>)
/// ```
///
/// The Alert can have up to 2 customisable buttons: a required Default button and an _optional_ Cancel button.
///
/// Closures can be _optionally_ passed to perform actions upon Button presses.
///
/// ### Parameters:
/// - id: Alert binding objects need to conform to Identifiable; a default UUID value is generated automatically
/// - title: _Required_ title to be displayed in the Alert
/// - message: _Required_ body message to be displayed in the Alert
/// - defaultButtonTitle: _Optional_ title for the confirmation button; if not provided, defaults to "OK"
/// - defaultButtonAction: _Optional_ closure containing code to be executed when the Default button in pressed
/// - hasCancelButton: By default, no Cancel button is displayed; set to `true` to include a default localised Cancel button in the Alert
/// - cancelButtonAction: _Optional_ closure containing code to be executed when the Cancel button in pressed
///
/// ---
///
/// ### Usage:
/// 1. In your SwiftUI file, declare a
///
/// ```swift
/// @State private var customSwiftUIAlert: CustomSwiftUIAlert?
/// ```
///
/// 2. Apply the provided ``CustomAlertViewModifier`` modifier to your SwiftUI View:
///
/// ```swift
/// content
/// .alert(with customSwiftUIAlert: Binding<CustomSwiftUIAlert?>)
/// ```
///
/// 3. Whenever you need to display an Alert at runtime, set the `customSwiftUIAlert` variable _(1)_ to a new ``CustomSwiftUIAlert`` object:
///
/// ```swift
/// customSwiftUIAlert = CustomSwiftUIAlert(title: "Uh oh",
/// message: "The server went up in flames",
/// defaultButtonTitle: "I'm sad",
/// defaultButtonAction: {
/// print("You need to purchase a new server")
/// },
/// hasCancelButton: true,
/// cancelButtonAction: nil)
/// ```
///
/// **SwiftUI will take care of presenting the Alert when `customSwiftUIAlert` has a value**.
///
struct CustomSwiftUIAlert: Identifiable {
let id = UUID()
var title: String
var message : String
var defaultButtonTitle = "OK"
var defaultButtonAction : (() -> Void)? = {}
var hasCancelButton = false
var cancelButtonAction : (() -> Void)? = {}
}
struct CustomAlertViewModifier: ViewModifier {
@Binding var customSwiftUIAlert: CustomSwiftUIAlert?
func body(content: Content) -> some View {
content
.alert(item: $customSwiftUIAlert) { customSwiftUIAlert in
if customSwiftUIAlert.hasCancelButton {
Alert(
title: Text(customSwiftUIAlert.title),
message: Text(customSwiftUIAlert.message),
primaryButton: .default(
Text(customSwiftUIAlert.defaultButtonTitle),
action: customSwiftUIAlert.defaultButtonAction
),
secondaryButton: .cancel(customSwiftUIAlert.cancelButtonAction)
)
} else {
Alert(
title: Text(customSwiftUIAlert.title),
message: Text(customSwiftUIAlert.message),
dismissButton: .default(
Text(customSwiftUIAlert.defaultButtonTitle),
action: customSwiftUIAlert.defaultButtonAction
)
)
}
}
}
}
extension View {
/// Convenience custom View modifier to present a ``CustomSwiftUIAlert`` Binding at runtime
func alert(with customSwiftUIAlert: Binding<CustomSwiftUIAlert?>) -> some View {
modifier(CustomAlertViewModifier(customSwiftUIAlert: customSwiftUIAlert))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment