Last active
June 20, 2023 14:10
-
-
Save stephancasas/f78a2fdb4a6055d50b3473239e6c4a76 to your computer and use it in GitHub Desktop.
Customizable NSAlert with suppression checkbox in SwiftUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SwiftUI_NSAlertExampleApp.swift | |
// SwiftUI_NSAlertExample | |
// | |
// Created by Stephan Casas on 6/20/23. | |
// | |
// This example requires the [NSViewProxy](https://github.com/stephancasas/NSViewProxy) | |
// package to acquire the pre-draw window context in `ContentView`. | |
// | |
import SwiftUI | |
import Combine; | |
import NSViewProxy; | |
// MARK: - Main App | |
@main | |
struct SwiftUI_NSAlertExampleApp: App { | |
var body: some Scene { | |
WindowGroup { | |
ContentView() | |
} | |
} | |
} | |
// MARK: - Content View | |
struct ContentView: View { | |
@State private var alertResult: String? = nil; | |
private var alertSubscriber = PassthroughSubject<String, Never>(); | |
var body: some View { | |
VStack(content: { | |
Button(action: self.showAlert, label: { | |
Text("Show Alert") | |
}) | |
if let alertResult = self.alertResult { | |
Text(alertResult).padding() | |
} | |
}) | |
.padding() | |
.proxy(to: .window, using: self.configureCustomAlert) | |
.onReceive(self.alertSubscriber, perform: self.handleAlertResult) | |
} | |
// MARK: - Handle Custom Alert Result | |
private func handleAlertResult(_ result: String) { | |
self.alertResult = result; | |
} | |
// MARK: - Configure Custom Alert | |
@State private var showAlert: () -> Void = { } | |
private func configureCustomAlert(_ window: NSWindow) { | |
self.showAlert = { | |
let customAlert = NSAlert(); | |
customAlert.alertStyle = .critical; | |
customAlert.messageText = "Are you sure you want to continue?"; | |
customAlert.informativeText = "What you're doing sounds like a terrible idea."; | |
/// The value of `NSApplication.ModalResponse` in the provided callback | |
/// is `RawRepresentable<Int>` with values starting at 1000. | |
/// | |
let options: [Int: String] = [1000: "Continue", 1001: "Cancel"]; | |
customAlert.addButton(withTitle: options[1000]!) | |
.hasDestructiveAction = true; | |
customAlert.addButton(withTitle: options[1001]!); | |
customAlert.showsSuppressionButton = true; | |
customAlert.suppressionButton?.title = "Don't tell me what to do"; | |
customAlert.beginSheetModal( | |
for: window, | |
completionHandler: { (response: NSApplication.ModalResponse) in | |
let choice = options[response.rawValue] ?? "Unknown"; | |
let suppression = (customAlert.suppressionButton?.state.rawValue ?? 0) == 1; | |
self.alertSubscriber.send( | |
"User picked \"\(choice)\(suppression ? "\" and will ignore future alerts." : ".\"")" | |
); | |
}); | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment