My main question is where my code goes in the default template.
Assuming a single-window app, I make a separate custom controller to own that window, and I have my app delegate own that controller.
So:
The app delegate
- Owns the custom controller.
- Creates it in
applicationWillFinishLaunching:
(note: not Did
; I change this).
- Releases it (and
nil
s out the instance variable) in applicationWillTerminate:
.
- Does not own the primary window (I remove that ivar and all references to it).
- Responds to
applicationShouldTerminateAfterLastWindowClosed:
with YES
, so that the user can quit the application either by specifically quitting or by closing the primary window.
- May also respond to
application:openFile:
or application:openFiles:
, typically by passing the file(s) along to the controller to import or something.
The MainMenu nib
- Owns the app delegate.
- Does not contain the primary window (I remove the blank one).
The primary-window controller
- Owns the primary window.
- Owns the model displayed in the window.
- Creates initial/empty model in
init
.
- Loads the primary-window nib with itself as owner in
init
.
- Closes and releases window (first) and releases model (second) and subordinate controllers (third) in
dealloc
.
The primary-window nib
- Named similarly to the controller; e.g., “SnippetListController” for the controller and “SnippetList” for the nib.
- Contains the primary window.
- Primary window has “visible on launch” (really on nib load) turned on and “release when closed” turned off.
The advantage of all of this is that the lifetime of every object but the app delegate is clear and explicit, as is the area of responsibility. My app delegate is little more than that; the only thing it does that isn't specifically an app-delegate job is owning the primary-window controller. Likewise, the primary-window controller does nothing but own the primary window and whatever model I have to show in that window. And at quit time, everything but the app delegate gets deallocked.
For document-based apps, I stick pretty close to the template. I delete any template methods I don't need to customize, and I may switch one or both of the I/O methods to one of the other versions (e.g., from readFromData:ofType:error:
to readFromURL:ofType:error:
), and maybe delete the write method if I'm writing a viewer only; that's about it.