After messing around with iOS apps, I thought I'd give a Cocoa app a whirl assuming things would be very similar. So I have a single window app with a split view and some NSTableView
s (think iTunes) and I'm looking for a place to put my code that will fetch data from the web to fill the tables.
In iOS I would put this in the viewDidLoad
method of the appropriate UIViewController
subclass. The UITableViewDataSource
would then access this data to populate its cells.
Now I have an NSWindow
for which I could do a similar thing but how do I make a NSWindowController
for it? Is this even what I want? I could put it in the AppDelegate
but doesn't seem right.
The difference between iOS and OS X is that there's only one window in iOS but there can be multiple in OS X. NSViewControllers
in OS X work differently than UIViewControllers
in that the NSViewController
is designed to load and handle a single view, while UIViewControllers
(apologies for my relative lack of iOS knowledge) seem to handle multiple views and provide much more of the glue between views.
Even the Apple docs write that:
In Mac OS X, AppKit view controllers are assistants to the window controller, which is ultimately responsible for everything that goes in the window.
Hence, the counterpart for UIViewController
in OS X isn't NSViewController
, but rather NSWindowController
, which does provide for OS X much of what UIViewController
does for iOS by managing the entirety of an individual window and the layout/content/interaction of the views within.
In your case, I would use an NSWindowController
- though if the app is very simple, the App Delegate
works too; and if the app is very complex, then using a NSViewController
to split up the code wouldn't be a bad idea.
The best way to do use an NSWindowController
would be to programatically load it in the App Delegate using [[CustomWindowController alloc] init]
and
@implementation CustomWindowController
- (id)init
{
self=[super initWithWindowNibName:@"CustomWindowNibName"];
if(self)
{
//perform any initializations
}
return self;
}
@end
Or calling
[[CustomWindowController alloc] initWithWindowNibName:@"CustomWindowNibName"];
directly (and overriding initWithWindowNibName) if you want it to be reusable.
And you can delete the default window in MainMenu.xib.
Fundamentally, more often than not, an NSWindowController manages a window instantiated in its own nib file. The NSWindowController usually owns that nib file. (Though it is possible to have it manage a programmatically created window, that isn't usually how it's done.)
To be able to use a custom NSWindowController
, you therefore need to make your window-to-be-managed in a separate nib/xib file. (using the default xib file means that you allow Cocoa to automatically instantiate a NSWindowController without opportunity for subclassing; you cannot use a custom NSWindowController
with the default NSMainNibFile. For a simple app, just put all the controller code in the NSApplication/App Delegate)
In Xcode 4 at least, the process involves creating a xib with the window template and the custom NSWindowController
class, instantiating the CustomWindowController
class based on that nib in -init or wherever and then calling [CustomWindowController showWindow:self];
(or if that doesn't work, -makeKeyAndOrderFront:
) to get the window to actually show (in - (void)applicationDid/WillFinishLaunching:(NSNotification *)aNotification
might be a nice place).
To stop the default window from showing I just delete it. There's probably a better way but I don't know that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With