Reputation: 7204
I have opened my window in the traditional way, but I want to run some code when the window is closed by clicking the close box (red button). Is there a good way of doing this?
func openMyWindow()
{
myWindow = (NSWindow(
contentRect: NSRect(x: 100, y: 100, width: 100, height: 600),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false))
myWindow!.contentView = NSHostingView(rootView: MyWindowView())
myWindow!.makeKeyAndOrderFront(nil)
}
Upvotes: 8
Views: 1670
Reputation: 8557
Great question.. I struggled on that a time ago as well.
You can make your AppDelegate
or class conform to NSWindowDelegate
protocol.
Then pass self
as the delegate of the window
myWindow.delegate = self
And implement following function to be notified by the closing action
func windowShouldClose(_ sender: NSWindow) -> Bool
{}
Edit:
When you are using SwiftUI life cycle, you can add an AppDelegate
. You can also implement your own WindowManager
class. Here is an example:
class WindowManager : NSObject, NSWindowDelegate {
var popUpWindow : NSWindow? = nil
override init() {}
func openMyWindow()
{
popUpWindow = (NSWindow(
contentRect: NSRect(x: 100, y: 100, width: 100, height: 600),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false))
popUpWindow!.contentView = NSHostingView(rootView: PopUpView())
popUpWindow!.makeKeyAndOrderFront(nil)
popUpWindow?.delegate = self
}
func windowShouldClose(_ sender: NSWindow) -> Bool
{
print("Window will close")
return true
}
}
struct PopUpView : View {
var body: some View {
Text("This is a new popup view")
}
}
Create and hold that class in your struct _: App
and open Windows via this Manager.
@main
struct macSwiftUICycleApp: App {
let persistenceController = PersistenceController.shared
let windowManager : WindowManager = WindowManager() //<< Here keep the instance of your WindowManager
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.onAppear {
windowManager.openMyWindow() //<< Just a test to open another window on startup
}
}
}
}
Upvotes: 7
Reputation: 258541
If the code you want to run is independent of context then the simplest solution is to replace close action for window and run your code there, like
func openMyWindow()
{
// ... other your code
myWindow!.contentView = NSHostingView(rootView: MyWindowView())
let closeButton = myWindow!.standardWindowButton(.closeButton) // << !!
closeButton?.action = #selector(NSWindow.doMyClose(_:)) // << !!
myWindow!.makeKeyAndOrderFront(nil)
}
extension NSWindow {
@objc
func doMyClose(_ sender: Any?) {
// ... run your code here
self.close() // << make standard window close
// ... or here
}
}
if you want to execute some closure with captured variables, then the approach is the same but with custom handler class which would hold window and closure to perform.
Upvotes: 1