If you’ve been following me on Twitter, you’ve probably seen me make reference to @secondgear.app 3.0. I am indeed working on a third app to put in the garage, and it is also offering me the opportunity to get acquainted with a lot of technologies I haven’t exactly used outside of staring at some samples before. Notably:
- Core Data
- Cocoa Bindings
NSViewController- Unit testing
- And more!
One of the trends in Mac development in recent years is the prevalence of single window applications such as iPhoto, Aperture and Coda. Single window interfaces can be less complex in terms of user interaction, but it can also lead to a more complex underpinning if you don’t watch yourself where you have a single window controller with everything in it1. Apple has aimed to address this with the NSViewController class, which lets you manage portions of the user interface in their own separate class. If you have done any work on the iPhone it’s similar to UIViewController in many aspects.
Building your single window app using NSViewController is something any new Cocoa programmer should embrace, but most of the tutorials and walkthroughs I’ve seen online do not make use of it.
As a starting point, I picked the Build A Core Data Application tutorial on CocoaDevCentral. The article walks you through creating a “Blogging” application that stores posts, categories and authors. The tutorial is a great introduction to Core Data’s concepts, but it also shoves all of the logic into a single nib and window controller. This is understandable given it being a tutorial on Core Data rather than general app architecture, but I hit a bit of a stumbling block when trying to wrap my head around how to use my Core Data entities through multiple view controllers.

I’ve uploaded a sample project to my Github account that should be a good starting point. Rather than having everything in a single window, I extracted the table view and the post details into their own view controllers.
The architecture of the application should be fairly straightforward:
- MDVCAppDelegate: This has all the Core Data boilerplate code and
NSApplicationDelegatemethods. One thing to note is that I am creating default categories and authors in themanagedObjectContextmethod if they don’t exist. I picked up that tip from Marcus Zarra’s Core Data book. I am not really a big fan of having all the Core Data junk stuffed into the AppDelegate, but shifting it off to its own controller can be an exercise for the user. - MDVCMainWindowController: The main window controller has the base NSArrayController for all the posts. The nut of this class is in the
windowDidLoadmethod.
- (void)windowDidLoad
{
static NSInteger kSourceListViewIndex = 0;
static NSInteger kDetailViewIndex = 1;
self.postsListsViewController = [[MDVCPostsListViewController alloc] initWithArrayController:self.postsArrayController];
NSView *sourceListSplitViewContentView = [[self.splitView subviews] objectAtIndex:kSourceListViewIndex];
NSView *sourceListView = [self.postsListsViewController view];
[sourceListView setFrame:[sourceListSplitViewContentView bounds]];
[sourceListView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[sourceListSplitViewContentView addSubview:sourceListView];
// And now let's load the detail view.
self.postDetailViewController = [[MDVCPostDetailViewController alloc] initWithArrayController:self.postsArrayController];
NSView *detailSplitViewContentView = [[self.splitView subviews] objectAtIndex:kDetailViewIndex];
NSView *detailView = [self.postDetailViewController view];
[detailView setFrame:[detailSplitViewContentView bounds]];
[detailView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[detailSplitViewContentView addSubview:detailView];
}
What I’m doing is allocating an instance of each view controller and passing it a reference to the window controller’s array controller to bind against.
- MDVCPostsListViewController: If you look in the Xib, you’ll see that everything is bound through
Files Owner.postsArrayController. This is our reference to the main window controller’s array controller. Do take note that the NSTableView has itscontent,selectionIndexesandsortDescriptorsbound. - MDVCPostDetailViewController: Like the other view controller, this one binds everything through
Files Owner.postsArrayController, but goes throughselectionrather thanarrangedObjectssince it displays the details for the currently selected post. - MDVCCategoriesWindowController: A window controller that lets you adjust the categories the posts can be associated with. Nothing too sexy here.
- MDVCAuthorsWindowController: Same as above, but for authors.
This is how I do it, but I’m sure there’s another (and possibly better way). One idea that comes to mind is using an NSObjectController in MDVCPostDetailViewController and having it observe the selection property of the parent array controller to manually set the controller’s content object property when the selection changes.
I put it up on Github mainly because it makes it a lot easier to update and track the changes. If you find ways to improve the code, please let me know. I am mainly posting all of this for the Google Gods in hopes that someone will someday find this, learn something and have a better application architecture going forward.
Update: Martin Pilkington has responded with a slightly different approach to the sample app. He extracts the Core Data implementation out of AppDelegate and into its own set of classes as well as relies more on KVO than abusing NSArrayController through Interface Builder. His version also uses Rentzsch’s excellent MOGenerator to generate the Core Data classes.
- Martin Pilkington wrote a bit about this in his Size Matters post [↩]

