Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is AppKit destroying my "Saved Application State" folder on normal app termination?

SETUP:

  • OS X 10.9.0 (13A603)
  • Xcode Version 5.0.2 (5A3005)
  • Normal Cocoa Document-Based Application

I have developed a typical Cocoa Document-Based OS X Application.

My intention is to support Apple's User Interface Preservation feature to restore the open Documents/Windows from the prior run of the app.

This is supported by default in Document-based apps.

I am not overriding any of the related methods such as:

-[NSWindow isRestorable]

-[NSResponder encodeRestorableStateWithCoder:]
-[NSResponder decodeRestorableStateWithCoder:]

-[NSApplication restoreWindowWithIdentifier:state:completionHandler:]
-[NSDocumentController restoreWindowWithIdentifier:state:completionHandler:]

(Note: -[NSWindow isRestorable] in my Document windows is already returning YES by default. Presumably this is a feature of Document-Based apps)

I don't think I'm doing anything out of the ordinary in my app related to UI Preservation.

PROBLEM:

UI Preservation in my app is not working. But it's failing in a very odd way. As I run my app (either by building and running it in Xcode or by running a distribution build independently), the normal Saved Application State folder is correctly created and populated with the correct application state information.

Correct Saved Application State Folder Contents

If I force quit my app (by abruptly stopping a running Xcode build or via the Dock Force Quit menu item), and then restart my app, the UI Preservation feature works perfectly. The app finds the info stored in the Saved Application State Folder and correctly restores open Documents/Windows from the prior run.

However, whenever I Quit my app normally, the entire Saved Application State folder is deleted (I can see this happen in the Finder). So the next time I launch my app, there's no stored state to restore, and restoration fails.

I've tracked this Folder deletion down to happening sometime after -[NSApplication terminate:] is called.

So I put a Symbolic Breakpoint on unlink(), and sure enough, one-by-one some code in AppKit is purposely deleting the Saved Application State folder and all of its contents.

enter image description here

Note the call to unlink() from a queue called NSPersistentUI I/O on the main thread from NSApplicationMain. (This is not coming from my code obviously)

Why is AppKit destroying my Saved Application State folder on normal app termination?

Is this normal?

How can I stop this?

like image 397
Todd Ditchendorf Avatar asked Jan 18 '14 03:01

Todd Ditchendorf


2 Answers

We override the checkbox @indragie mentions for our sandbox app, since for new accounts that box is unchecked, and so critical state restoration functionality is lost.

The code is as easy as adding this to your main() routine:

[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"NSQuitAlwaysKeepsWindows"]; // override stupid global preference, so our state restore works properly
like image 191
Wil Shipley Avatar answered Sep 17 '22 08:09

Wil Shipley


Make sure that this box is unchecked in System Preferences > General:

Close windows when quitting an application

When this box is checked, it disables state restoration system wide and results in the behaviour you described.

like image 27
indragie Avatar answered Sep 18 '22 08:09

indragie