NSViewController, the New C in MVC - Pt. 2 of 3
In the last post on NSViewController, I described the need for a view controller class that is part of a sound controller architecture, especially when developing an application with a single window interface. In this post, Jonathan Dann and I will share the design we came up with for integrating NSViewController into the existing Cocoa MVC application architecture using NSWindowController as the glue.
Before, we do that…
Meet Jonathan.
I’m currently training with the National Health Service in the UK, working towards becoming a state-registered Medical Physicist. I was introduced to programming during my Bachelor’s degree where I did a short course in C. During my Master’s degree I learnt some FORTRAN and then had my first experience of object-oriented programming during that year. Since then I’ve been learning as much as I could about Cocoa, design patterns, and the whole world of Mac programming. I’ve begun to write my first app, which will be available sometime around September, which really began life as a personal project when the tool I was using didn’t work right and didn’t fit properly within OS X.
As my code grew in size I soon realised that I needed a controller for some of my more complex view behaviour, NSSplitViews, NSTextViews, NSOutlineViews all need delegates to unlock their power and when all of this was in the same window controller I got the feeling it was doing work that it shouldn’t have to. I started using NSViewController and came to the conclusion that it didn’t quite fit in my design, after considering how MVC should work I asked on cocoa-dev how other people use it. Sure enough, it sparked some conversation. I think that Apple has left the use of this class up to developers intentionally, maybe they will extend it in future releases, maybe having a structured controller system seems a little abstract for smaller programs, but I think it makes things easier to maintain in the long-run.
After using the class for a while I am of the mind that each view in an app could potentially have its own controller, although this would probably be overkill; the only structure that then makes sense is a tree, just like the view hierarchy. I now use these classes extensively to inform the views, for example, how they should look: the view can then draw itself based on those options it gets from its overlord.
The XS (extra special) Controllers
Our solution includes to two classes:
- XSWindowController, an NSWindowController subclass
- XSViewController, an NSViewController subclass
You can find these classes in the example project (XCode 3.0). Dowonload it here.
The Goal of This Design
The goal of our design is simple: We want a way to manage a group of view controllers in a way that fits in nicely with the current Cocoa MVC architecture.
When building a Cocoa app, the controller layer of the architecture can be described very loosely as:
- NSDocument contains a list of NSWindowControllers
- Each window controller has an associated window

We want to extend this design so that:
- NSDocument contains a list of NSWindowControllers*
- Each NSWindowController conains a list of NSViewControllers
- Each NSViewController contains a list of subcontrollers
- Each NSViewController has an associated view

*Our changes happen beneath the document layer, so it is also a valid design for applications that aren’t document-based.
XSViewController and XSWindowController
In order to meet our goals, we enhanced Cocoa’s NSWindowController and NSViewController classes.
In XSViewController, we added a list of subcontrollers and the necessary methods to manage that list. We also gave the view controllers a reference to the window controller.
In XSWindowController, we added a list of view controllers. The window controller is the “host” for the view controllers, so when the window controller is created and destroyed by the document, it does the same to the view controllers. The window controller also does some extra work that is necessary for the view controllers to be integrated smoothly into the existing Cocoa controller architecture. We’ll describe this work further down.
In this setup, you would use the following XSWindowController methods to add and remove view controllers,
- (void)addViewController:(XSViewController *)viewController; - (void)removeViewController:(XSViewController *)viewController;
In XSViewController, you can nest controllers and manipulate the structure of the controller tree using several methods that will be familiar to those who have worked with mutable arrays,
- (void)addChild:(XSViewController *)child; - (void)insertObject:(XSViewController *)child inChildrenAtIndex:(NSUInteger)index; - (void)insertObjects:(NSArray *)children inChildrenAtIndexes:(NSIndexSet *)indexes; - (void)insertObjects:(NSArray *)children inChildrenAtIndex:(NSUInteger)index; - (void)removeChild:(XSViewController *)child; - (void)removeObjectFromChildrenAtIndex:(NSUInteger)index;
As long as you use these methods to add and remove view controllers from the application, you will get all of the benefits of the design.
Quick design note:
We want to note here that we considered a design where the window controller contained one view controller that would be the root of a single view controller tree. We chose to keep a list of view controllers in the window controller because it feels redundant to have to make a second controller that represents the entire window.
In a perfect world, the view controllers and window controllers would actually be the same class, so that the window controller would be the root of a single tree of controllers. This isn’t possible, but we decided that we would design with that structure in mind anyway.
Working with Cocoa
So, after we had this system set up and running, making sure that memory management was handled properly, we had to handle some Cocoa-specific behaviors so that the view controllers were well integrated into the Cocoa application architecture. This is the “glue-code” of this design. There are two Cocoa-related issues that we had to consider.
Cocoa Consideration 1: Taking care of the Responder Chain
NSViewController is a subclass of NSResponder, but it needs to be added to the responder chain to receive action events from things like buttons and menu items. We decided that our design should patch the responder chain so that it runs through the view controllers like this:

We looked at two approaches to solving this problem. The first approach would be to handle the responder chain in the NSViewController class, so that when a view controller was added or removed from the tree, its super controller would make sure the responder chain was patched together correctly.
The other approach is to have the window controller do the responder chain patching whenever a view controller is added or removed.
Both of these approaches have their advantages and disadvantages.
The first approach would keep things logically clean and less glue-like. The view controllers wouldn’t have to communicate back to the window controller when they add or remove their subcontrollers. If this were the perfect design world, where the window and view controllers were in the same tree, this would be the obvious way to maintain the responder chain throughout a single hierarchy of controllers.
The second approach is just more simple in this particular setup. Since this isn’t the perfect design world, the code that adds the view controllers to the responder chain would have to be repeated in both classes anyway. Letting one class handle the responder chain keeps this code centralized.
We decided to use the second approach. We don’t feel that there is a perfect solution to this problem and that either approach works fine.
The method that patches the responder chain is in XSWindowController:
- (void)patchResponderChain;
The source code will show how simple it is to keep the responder chain looking like it does in the diagram.
Consideration 2: Bindings and Observations
Bindings and Key-Value Observing are powerful Cocoa mechanisms that help us to keep our controllers and our data models separate. Most view controllers and window controllers will have bindings or KVO set up in some way.
In NSViewController, there is the idea of a “representedObject”. According to the documentation of NSViewController:
Declaring a generic representedObject property, to make it easy to establish bindings in the nib to an object that isn’t yet known at nib-loading time or readily available to the code that’s doing the nib loading.
This is a handy feature of NSViewController, especially if you are setting up all of your bindings in Interface Builder, but in a more complex setup, the single “representedObject” may not be the best way to expose a view controller to the data in an application.
There are situations where you might want to set up several KVOs and bindings in code and then remove them when you don’t need them anymore. If you forgo the “representedObject” as a means to set up KVO with your application’s data, you might come across this message in your logs when you close the document:
An instance (so-and-so) of class (so-and-so) is being deallocated while key value observers are still registered with it. Break on _NSKVODeallocateLog to start debugging.
We decided to go ahead and handle the possibility of these situations by adding a method to XSViewController called,
- (void)removeObservations;
This gives the view controllers a chance to remove observations or bindings that they set up in code before the data is released. The window controller has to manage the timing of this. In XSWindowController, we do it right before the window closes, in an implementation of the window’s delegate method,
- (void)windowWillClose:(NSNotification *)notification;
The window controller tells its view controllers to “removeObservations” here and they pass the message on to their subcontrollers. The window controller and document can then release data as they normally would in their implementations of “dealloc”.
Quick notes on subclassing:
If an XSViewController subclass implements the “removeObservations” method, it is responsible for calling super’s implementation so that the message will continue to be propagated down its branch of the tree.
If an XSWindowController subclass needs to implement “windowWillClose”, it should be sure to call super’s implementation so that the view controllers will get the message to remove their observations. The timing of this message is important, so if you are releasing some data here, be sure to call super first.
Using “windowWillClose” for a feature like this may not be the best solution, but as far as we can tell, it seems like the most convenient place to perform this task.
That’s It.
With these few enhancements, we now have two new abstract super-classes for our controllers, XSWindowController and XSViewController. When we subclass them to build our UIs, we get the controller architecture that we illustrated at the beginning of the post and the following features built in to our view controller:
- Automatic memory management!
- Automatic inclusion in the responder chain!!!
- A designated method for removing observations or bindings!
- A relationship with the window controller and document!
This design will become more and more useful as your single window interface becomes more complex, especially as your feature set changes over the life-time of your development. With this architecture in place, you have more flexibility to try things out and change your design without worrying about breaking the responder chain (which is not that easy to debug) or causing memory leaks by accident as you’re working rapidly to test UI designs. As long as you keep to MVC design principles, it is possible to create self-contained view controllers that can be plugged in to, and unplugged from, your UI with very little hassle.
Next Time…
First, thanks so much to Jonathan for working on this post with me. It was great to have the chance to brainstorm with another developer, especially one whose applications are completely different from the ones I work on every day. Working with him on this design helped to get me out of my usual mind-set and to isolate the issues that are truly common to any Cocoa application rather than unique to my own projects. This has been an educational and super-productive experience for me – Thanks, Jonathan!
AND a another big thanks to Jonathan for setting up the Xcode 3.0 example project and the source code!
In the next and last post about NSViewController, I’m going to discuss its relationship to NSView and the view hierarchy in more detail. One of the many important jobs of a view controller is to help to build and manage the view hierarchy during runtime. This is especially important when coding a single window interface that needs to give users access to many different features that can’t all be displayed in the window at one time.
Anyone who is sick of me writing about autoresizing should just skip the next installment ; ) ( or in Japanese, ^_- )
Resources
The example project contains XSWindowController and XSViewController, which contain all the nitty-gritty implementation details. There is also an example app that shows how you could subclass these classes to build a UI based on the XS controllers.
Cocoa Event-Handling Guide: The Responder Chain
Introduction to Document-Based Applications Overview
NSViewController Class Reference
NSWindowController Class Reference
Introduction to Key-Value Observing Programming Guide
Introduction to Cocoa Bindings Programming Topics
UPDATE 04/23/08
We updated the example project today. The biggest change we made is in XSViewController. We were previously setting the “representedObject” of child controllers to be that of its parent. In the new version we don’t deal with “representedObject” in any way. You can just use NSViewControllers methods to set them case-by-case.
Just XSViewController and XSWindowController
Tags: MVC, NSViewController, NSWindowController, ResponderChain, SampleCode
April 17th, 2008 at 8:45 pm
This is genius stuff. Thanks for writing it up.
April 17th, 2008 at 9:12 pm
Brilliant. Great work Cathy and Jonathan. Again, another fantastic article.
April 17th, 2008 at 10:06 pm
Great articles, very useful! What do you use to create your diagrams? Thanks
April 17th, 2008 at 10:25 pm
Hi, Thierry. Thanks
I use OmniGraffle for making diagrams.
April 17th, 2008 at 10:42 pm
Ah. I was afraid you would say that. The thing is, I am constantly looking for a nice little class diagram editor.
I know OmniGraffle, but its extensive feature set makes it too much expensive for what I want to do.
There is also Xcode class diagram editor, but I find it very limited (no association, aggregation, composition, etc…), or maybe I have not found the right way to use it.
I use ArgoUML at the moment, which provides all the diagrams I need, but is not integrated very well into Mac OS X. It is written in Java, and you can tell it is with one glance at the main window.
I considered writing one myself, but before that, I want to make sure there is not an existing app which could suit me.
April 17th, 2008 at 10:47 pm
Yeah, I’ve just gotten to know the bits of OmniGraffle that I need to know, but it is alot like using Photoshop just to change the size of an image…too much interface.
If you do make one, let me know, I am always on the look out for something more simple myself.
April 17th, 2008 at 11:06 pm
I’ll let you know, but don’t get your hopes too high, I don’t really have the time at the moment.
I am not fond of web apps usually, but I think it would be the sort of app useable in a browser. I found this website: http://www.gliffy.com It seems to be a good candidate for a simple diagram editor, but the free version is feature-limited ad-unlimited, and the other versions need a membership paid monthly. I was not able to find an alternative. The Quest continues!
April 17th, 2008 at 11:21 pm
> NSViewController is a subclass of NSResponder, but it needs to be added to the responder chain to receive action events from things like buttons and menu items. We decided that our design should patch the responder chain so that it runs through the view controllers like this:
In a word: Depth-first.
April 18th, 2008 at 1:17 am
Yeah, but isn’t the diagram so much prettier
April 18th, 2008 at 10:21 pm
hi i enjoyed the read
April 21st, 2008 at 6:16 am
I feel so silly like I did something wrong, but when I try to compile the example project in the beginning of this entry, I get this message!
Internal error occurred while creating dependency graph: ASSERTION FAILURE in /SourceCache/DevToolsBase/DevToolsBase-921/pbxcore/SpecificationTypes/XCCompilerSpecification.m:267
Details: arch should be a non-empty string, but it’s an empty string
I tried changing my architecture to my Mac’s arch type, but it was no good! What is going on?
April 22nd, 2008 at 5:21 pm
Hi Anonymous,
I’ve seen this and I think it has to do with backwards compatibility with the xcode project…maybe someone else has an idea?
We’ll be posting an update to the code in the next couple of days and I’ll make just the source code available as well as the xcode project.
April 23rd, 2008 at 3:57 pm
The arch issue is due to the Xcode beta backward compatibility. To fix the problem, select the arch setting and press delete.This will have the setting go back to the default.
May 23rd, 2008 at 11:01 am
Great work! But when will we see part three?
May 23rd, 2008 at 11:11 am
Sooooon!!! Sorry it’s taking so long…combination of being busy with my job and having a bit of writer’s block.
June 3rd, 2008 at 4:33 pm
Shouldn’t the XSViewController have a default setRepresentedObject implementation that forwards setRepresentedObject to all it’s children?
June 4th, 2008 at 5:04 am
Hi Michael,
We had it that way at one point, but changed it because it’s not necessarily true that a subcontroller will want the same represetned object as its supercontroller.
After thinking about it for a while we decided that the way data is organized and made accessible to the view controllers is going to be different depending on the application. We didn’t want this design to impose the idea that it should all be centralized in one single “representedObject”. That’s just one way to go about it. Other applications might have a more complicated setup.
So, we’re leaving it up to you to decided how to work with the represetned object for the view controllers.
June 6th, 2008 at 5:45 pm
Speaking of representedObject — it’s worth noting that default setRepresentedObject implementation in NSViewController (not suprisingly) retains the object. So if you use it to represent your document (NSDocument) subclass you end up with circular references/leak.