Reputation: 1094
I have an app that has a few windows defined as a windows group in the structure conforming to App in the main scene:
WindowGroup("StandingsView") {
StandingsView()
.environmentObject(appServices)
}
.handlesExternalEvents(matching: Set(arrayLiteral: "StandingsView"))
The appServices take some time to be configured, so I do not want to automatically restore the windows at start. I create the windows upon user selections being valid, the services being fully configured, and the user pressing a 'start' SwiftUI button:
if let standingsURL = URL(string: "raceStratLiteApp://StandingsView") {
NSWorkspace.shared.open(standingsURL)
}
I've tried closing the windows in the appDelegate's applicationShouldTerminate(). I've also tried setting the isRestorable to false in applicationShouldTerminate:
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
for window in NSApplication.shared.windows {
window.isRestorable = false
}
return .terminateNow
}
Are there any other methods to not restore a window? or better yet, to be able to programmatically restore it with its previous size, etc but launch only on user direction to 'start'
TIA
Upvotes: 7
Views: 918
Reputation: 614
I use the following on a per window basis. It’s a view modifier so you can restrict it to a particular view instead of applying it to all views.
struct WillRestore: ViewModifier {
let restore: Bool
func body(content: Content) -> some View {
content
.onReceive(NotificationCenter.default.publisher(for: NSWindow.didBecomeKeyNotification), perform: { output in
let window = output.object as! NSWindow
window.isRestorable = restore
})
}
}
extension View {
func willRestore(_ restoreState: Bool = true) -> some View {
modifier(WillRestore(restore: restoreState))
}
}
struct AboutRiverMakerContent: View {
var body: some View {
HStack(alignment: .center) {
Text("Your Text Here")
}
.willRestore(false)
}
}
If you want other windows to restore, you .willRestore
or set the optional parameter for.willRestore
to true
, the window will restore. I have tested this and it seems to work with multiple windows (have not tested with WindowGroup).
I use it for the About MyApp
to prevent it from restoring.
Edit: Added Window menu will show windows as marked non-restore. Minor code change.
Upvotes: 1
Reputation: 6390
The answer given by @Asperi was useful for most cases.
But when the app gets interrupted, for example when it crashes, NSQuitAlwaysKeepsWindows
seemed to be ignored.
What worked for me is to opt out every NSWindow
from state restoration.
The draw back is that this will affect every window at all. But no other solution worked on my case.
I had to use the NotificationCenter for this, listening to NSWindow. didBecomeKeyNotification, couldn't find a better alternative.
On your NSApplicationDelegateAdaptor
func applicationWillFinishLaunching(_: Notification) {
NotificationCenter
.default
.addObserver(forName: NSWindow.didBecomeKeyNotification,
object: nil,
queue: .main)
{ notification in
guard let window = notification.object as? NSWindow else { return }
window.isRestorable = false
}
}
Upvotes: 0
Reputation: 1094
The code solution as @Asperi suggests in the later comment:
func applicationDidFinishLaunching(_ notification: Notification) {
UserDefaults.standard.register(defaults: ["NSQuitAlwaysKeepsWindows" : false])
}
Upvotes: 5
Reputation: 1094
From the tip provide by @Asperi, writing the following to defaults will cease the writing of the window states:
$ defaults write <bundleid> NSQuitAlwaysKeepsWindows -bool false
So this is not a code change to the app, but rather an environment config the would be done on install.
I also deleted the savedState directory located at ~/Library/Saved Application State/<bundleid>.savedState
for archive builds and at ~/Library/Containers/<App Name>/Data/Library/Saved Application State/<bundleid>.savedState
for debug builds. Am not sure if that mattered but once doing these steps it solved the problem. Thanks @Asperi
Upvotes: 0