## Alerts for SwiftUI in macOS Only one alert may be attached to a view. To avoid collisions and clutter, one could handle alerts centrally using the `func alert<Item>(item: Binding<Item?>...` modifier on a senior view. The init above accepts a binding for any identifiable object and provides a closure to map it into multiple types of `Alert` views. To minimize code in that closure and simplify call sites, below is a minimalist example wrapper and implementation. This isn’t complex at all, but while the API is decent it could be simpler. ### Presentation ```swift @main struct SomeApp: App { @StateObject var coordinator: AppCoordinator var body: some Scene { WindowGroup() { MainWindow() .alert(item: coordinator.alert) { $0.present() } } } ``` ```swift class AppCoordinator: ObservableObject { var alert: Binding<AlertItem?> { Binding<AlertItem?> { self.root.state.alert } set: { [weak self] value in self?.root.dispatch(.setAlert(value)) } } } ``` When an alert is dismissed, SwiftUI sets the provided binding’s value to nil. Your buttons don’t need to clean up alert presentation state. ### Model (wrap/map Alert views) ```swift public struct RootState { var alert: AlertItem? } ``` ```swift public struct AlertItem: Identifiable { public var id = UUID() public var title: Text public var message: Text? public var dismiss: Alert.Button? public var primary: Alert.Button? public var secondary: Alert.Button? } public extension AlertItem { init(title: String, message: String? = nil, dismiss: Alert.Button? = nil) { self.title = Text(title) self.message = message == nil ? nil : Text(message!) self.dismiss = dismiss } init(title: String, message: String? = nil, primary: Alert.Button? = nil, secondary: Alert.Button? = nil) { self.title = Text(title) self.message = message == nil ? nil : Text(message!) self.primary = primary self.secondary = secondary } func present() -> Alert { guard let primary = primary, let secondary = secondary else { return Alert(title: title, message: message, dismiss: dismiss) } return Alert(title: title, message: message, primary: primary, secondary: secondary) } } ``` ### Presenting view model ```swift class FileMenuVM: VM { func save() { // If needs alert root.dispatch(.setAlert(overwriteAlert)) } lazy var overwriteAlert = AlertItem(title: Strings.Alerts.overwriteWarning, message: nil, primary: overwritePrimary, secondary: overwriteSecondary) lazy var overwritePrimary: Alert.Button = .default(Text(Strings.Alerts.overwriteWarningPrimary)) { // Actions } lazy var overwriteSecondary: Alert.Button = .destructive(Text(Strings.Alerts.overwriteWarningDestructive)) { // Actions } lazy var otherInitExample = AlertItem(title: Strings.Alerts.someAlert, message: nil, dismiss: nil) } ```