I'm dipping my feet into Cocoa for the first time.
Here's a simple question. OS X Lion supports Resuming of window state when an app is terminated and relaunched. Okay, good and fine.
But for document-based apps, can the same Resume feature also manage saving of window state when a document is closed and reopened later but without any quitting of the app? (In other words, can it manage each file's state persistently regardless of whether the app quits or not? Or do I have to manage it myself by saving the information in the documents' files?)
For instance, iWork '09 apps do do this sort of thing: if you close a saved document and reopen it, it will restore the window size, location, and scroller position. I don't know if it does this using Lion's Resume per se.
But, in contrast, OS X Lion's TextEdit restores windows when it is quit and restarted, but it does not remember window states when you close a document and reopen it. This makes me suspicious that using Resume without quitting might not be possible automatically (since maybe Pages keeps window states in its proprietary file format, but TextEdit doesn't since it uses plain text, RTF, HTML, etc. files).
I don't have access to the WWDC 2011 videos yet, and neither the OS X release notes, the OS X Application Programming Guide, nor the NSWindowRestoration API docs talk about this specifically.
So the question again: automatically remembering the state of a document window after closing and reopening it without quitting the app (like iWork does)...does Lion's Restore support this?
Thanks a lot!
But for document-based apps, can the same Resume feature also manage saving of window state when a document is closed and reopened later but without any quitting of the app? (In other words, can it manage each file's state persistently regardless of whether the app quits or not?
Not unassisted, no.
Or do I have to manage it myself by saving the information in the documents' files?)
Or somewhere else, yes.
My untested suggestion is to try using the window-restoration protocol yourself. When closing, send yourself encodeRestorableStateWithCoder:, then stash that data in your document (or wherever you want). When opening a document, if it has restorable state information, pass it to restoreStateWithCoder:.
Related
My document-based app immediately terminates the document upon cmd+w and it is not saved. How can I react to this and either prompt for saving the document or automatically save it?
Use the NSDocument method updateChangeCount(_:) to mark your document as edited, and Cocoa will take care of the rest!
Furthermore, if you use NSUndoManager for all changes, it updates the change count for you!
Most of the time, you should look for these kinds of "hooks" into existing Cocoa functionality, so that your app behaves exactly the same way as other OS X apps, and so that you inherit new features when new OS versions are released.
My app at launch time prompts the user with a template chooser, this works fine on Snow Leopard but on Lion the window never appears maybe due to restoration behaviour.
My app is NSDocument based and I use NSDocumentController to open the window on newDocument:(id)sender
Now on Lion no application delegate related to "untitiled" is called so I don't understard how to make it working
I think XCode 4 is NSDocument based and it shows the Startup Panel, how it does?
Another smart XCode Startup Panel's behaviour consists to show the panel only when no other windows are restored, again how this is implemented in Lion?
You're right to suspect the new restorable state behavior. The app may never be asked to create a new, empty document when relaunched/resumed. This is stated in the release notes:
As part of the restorable windows feature, the application delegate
may not be asked to create an Untitled window at launch in some
circumstances. This was found to cause crashes in certain apps, so
these apps will maintain 10.6 behavior of more often opening Untitled
windows. When these apps are recompiled on 10.7, they will acquire the
10.7 behavior. For maximum compatibility, do not depend on being asked
to create an Untitled window at launch.
They don't mention an alternative, and the document-based app documentation does not appear to have been updated yet with restorable state information.
As to your approach, you could change so that the template chooser is shown as a sheet on a new, empty doc window (like Pages or Instruments, for example). The document's contents are set when the template sheet is completed. This way, each new document shows its template sheet but this only happens if the user requests a new document, rather than relying on a fresh app launch (which you're no longer meant to do).
I want to observe any window on OSX if it is moved. I don't own the windows so i can't get to it directly so I think I have to use the Accessibility APIs. I found a solution for the current active Application here: How can my app detect a change to another app's window? but I can't figure out how I have to modify this that it works for any window which is open. I hope anybody could give me a hint in which direction I have to look.
As I mentioned in the comments, people usually only want to detect window-move events on focused windows. (As unfocused windows seldom move.) If you want to detect application switches, you can poke into this sample project by Apple that shows how to update iChat status with the frontmost application’s name. And as you said, there’s already a solution for an active window.
Unlike Windows, GNOME and most other GUI's, OS X application programs do not all terminate if the main window (or all the windows) of that application are closed.
For example, fire up Firefox, Safari, Word, or most document based apps. Either click the red dot in the corner or type cmdW to close the window. You can see that the menu of that program is still active, and the program is still running. With OS X newbies, sometimes you will see dozens of these windowless zombies running and they wonder why their computer is getting slower.
With some document based programs, there is some sense to not terminating the application if it has no windows. For example, with Safari or Word, you can still type CmdN and get a new document window for whatever that application was designed to do: browse the web (Safari) or type a new document (Word).
Apple is mixed with their design philosophy on this. Some close on the last window closed and some do not. Third party apps are even more mixed.
There are other apps that do close when their red close button is clicked. System Preferences, Dictionary, the Mac App Store, iPhoto and Calculator do terminate when the sole or last window is closed. iCal, Address Book, iTunes, DVD Player do not terminate.
What I find particularly annoying is the applications that do not have a logical "New Document" or "Open" function yet they do not terminate when the document window is closed. Example: fire up iTunes or Address Book and terminate the main window. There sits a zombie with no window and no function other than manually selecting "Quit".
It is easy to close the application after the last window closes. Cocoa even gives you notification of that event. Just add this to your application delegate:
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return YES;
}
My question is this: Is there any reason I should NOT terminate my application after the last window closes? Why is this so variable on OS X software? Unless the app has a "new" or "open" or some other clearly understood reason to not terminate with no window open, the failure to terminate seems like a bug to me.
Per Apple's Human Interface Guidelines (a guide for Mac developers):
In most cases, applications that are
not document-based should quit when
the main window is closed. For
Example, System Preferences quits if
the user closes the window. If an
application continues to perform some
function when the main window is
closed, however, it may be appropriate
to leave it running when the main
window is closed. For example, iTunes
continues to play when the user closes
the main window.
In general, never close a document based application when the last window closes. The user will expect to be able to open a new document without relaunching the application, and it will confuse them if they can't.
For non-document based applications, you need to consider a few things:
How long does it take for my application to open? If it takes more than a second, you should probably not quit.
Does my application need a window to be useful? If your application can do work without windows, you should not quit.
iTunes doesn't quit because, as Anne mentioned, you don't need a window to play music (question 2). It is also not based on Cocoa, so it is much more difficult to close after the last window, especially since it allows you to open windows for specific playlists so there are an indefinite number of possible windows to be open.
In my opinion, Address Book does not need to stay open. This could be a left-over design decision from older versions of OS X, or it could be that someone at Apple just thought it was better to leave it open (maybe so you can add a contact?). Both iTunes and Address Book provide access to their main interfaces through the Window menu, as well as a keyboard shortcut (Option+Command+1 for iTunes, Command+0 for Address Book).
The main iTunes window can be reopened from the 'Window' menu. Mail.app has similar behavior. I can't think of any applications that close when the last window is closed, and as such I don't think there's a good reason that your app should behave that way (in fact, i'm surprised its not in Apple's user experience guidelines, it would really bother me!).
One reason why you'd want to close e.g. the iTunes main window but keep the app open is to be able to use the app as sort of a server for third party scripts/applications. I rarely use the main iTunes interface, but instead control my music with a third party app. I also write AppleScripts for other apps that I launch instead of interacting with that app's interface.
I'm thinking of writing an X11 window manager which does for windows something like what TabKit does for tabs in Firefox (in its default tree view mode). To do this, I'd need to be to able to find out which window a window was opened from. Is there a standard way of finding this out?
(I've never done any X11 programming without using a cross-platform toolkit on top of X11, let alone writing a window manager.)
For the difficult cases - applications launching other applications, e.g. a word processor launching a web browser - there's going to be a need for co-operation between applications to track this information. The Zeitgeist project already seeks to track which documents were opened from which documents, which is close enough that I should probably work with Zeitgeist (and/or its KDE equivalent - Nepomuk?) to get this implemented.