Skip to content

Instantly share code, notes, and snippets.

@leogdion
Created August 23, 2023 14:20
Show Gist options
  • Save leogdion/4d11574af2d2b6099fa9d57156a1d874 to your computer and use it in GitHub Desktop.
Save leogdion/4d11574af2d2b6099fa9d57156a1d874 to your computer and use it in GitHub Desktop.
How to tap into the NSWindowDelegate
import AppKit
import SwiftUI
// .onCloseButton(self.$object.delegate, { _ in
// self.object.presentConfirmCloseAlert = true
// return false
// })
class NSWindowDelegateAdaptor: NSObject, NSWindowDelegate {
internal init(onWindowShouldClose: ((NSWindow) -> Bool)?) {
self.onWindowShouldClose = onWindowShouldClose
}
let onWindowShouldClose: ((NSWindow) -> Bool)?
func windowShouldClose(_ sender: NSWindow) -> Bool {
onWindowShouldClose?(sender) ?? true
}
}
private struct NSWindowDelegateAdaptorModifier: ViewModifier {
@Binding var binding: NSWindowDelegate?
// swiftlint:disable:next weak_delegate
let delegate: NSWindowDelegate
internal init(binding: Binding<NSWindowDelegate?>, delegate: @autoclosure () -> NSWindowDelegate) {
self._binding = binding
self.delegate = binding.wrappedValue ?? delegate()
DispatchQueue.main.async { [self] in
self.binding = self.delegate
}
}
func body(content: Content) -> some View {
content.nsWindowAdaptor { window in
assert(!self.delegate.isEqual(window?.delegate))
window?.delegate = delegate
}
}
}
extension View {
func nsWindowDelegateAdaptor(_ binding: Binding<NSWindowDelegate?>, _ delegate: @autoclosure () -> NSWindowDelegate) -> some View {
self.modifier(NSWindowDelegateAdaptorModifier(binding: binding, delegate: delegate()))
}
public func onCloseButton(_ delegate: Binding<NSWindowDelegate?>, _ closure: @escaping (NSWindow) -> Bool) -> some View {
self.nsWindowDelegateAdaptor(delegate, NSWindowDelegateAdaptor(onWindowShouldClose: closure))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment