Skip to content

Instantly share code, notes, and snippets.

@stephancasas
Last active June 20, 2023 14:10
Show Gist options
  • Save stephancasas/f78a2fdb4a6055d50b3473239e6c4a76 to your computer and use it in GitHub Desktop.
Save stephancasas/f78a2fdb4a6055d50b3473239e6c4a76 to your computer and use it in GitHub Desktop.
Customizable NSAlert with suppression checkbox in SwiftUI
//
// 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