Last active
January 17, 2025 12:09
-
-
Save kdeda/d7c2f6aafc066793e8cc8f4e398d0814 to your computer and use it in GitHub Desktop.
Open/Close NSWindow from SwiftUI.View
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
import SwiftUI | |
/** | |
hack to avoid crashes on window close, and remove the window from the | |
NSApplication stack, ie: avoid leaking window objects | |
*/ | |
fileprivate final class WindowDelegate: NSObject, NSWindowDelegate { | |
func windowShouldClose(_ sender: NSWindow) -> Bool { | |
NSApp.removeWindowsItem(sender) | |
return true | |
} | |
deinit { | |
NSLog("deallocated ...") | |
} | |
} | |
public extension View { | |
func openInNewWindow(_ introspect: @escaping (_ window: NSWindow) -> Void) { | |
let windowDelegate = WindowDelegate() | |
let rv = NSWindow( | |
contentRect: NSRect(x: 0, y: 0, width: 320, height: 320), | |
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], | |
backing: .buffered, | |
defer: false | |
) | |
rv.isReleasedWhenClosed = false | |
rv.title = "New Window" | |
// who owns who :-) | |
rv.delegate = windowDelegate | |
rv.contentView = NSHostingView(rootView: self) | |
introspect(rv) | |
rv.center() | |
rv.makeKeyAndOrderFront(nil) | |
} | |
} |
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
import SwiftUI | |
@main | |
struct WindowVanillaSwiftUIApp: App { | |
var body: some Scene { | |
WindowGroup { | |
ContentView() | |
} | |
} | |
} | |
struct ContentView: View { | |
var body: some View { | |
Button(action: { | |
ChildView().openInNewWindow { window in | |
window.title = "Window title" | |
} | |
}) { | |
Image(systemName: "paperplane") | |
} | |
.padding() | |
} | |
} | |
struct ChildView: View { | |
var body: some View { | |
VStack { | |
Spacer() | |
HStack { | |
Spacer() | |
Text("Hello World") | |
.padding() | |
Spacer() | |
} | |
Spacer() | |
HStack { | |
Spacer() | |
Button(action: { | |
NSApp.keyWindow?.close() | |
}) { | |
Text("Close") | |
} | |
} | |
.padding() | |
} | |
.frame(minWidth: 640, minHeight: 480) | |
} | |
} | |
struct ChildView_Previews: PreviewProvider { | |
static var previews: some View { | |
ChildView() | |
} | |
} |
Great stuff, finally done normal way
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you are using TCA from pointfree.co
You can pass in a scoped store to that ChildView