NSViewController, the New C in MVC - Pt. 1 of 3

iPhoto.jpg

Applications like iTunes and iPhoto have established a single window interface as the de-facto standard for modern Mac UI design. This design is great for end users, who no longer have to switch between several windows to be productive with their software. For developers, on the other hand, this design poses several challenges in terms of interaction design and software architecture, especially in the view and controller layers of the MVC architecture prescribed by Cocoa. This post is the first of three that will address this architectural design problem and, more specifically, examine the role of Cocoa’s new NSViewController class in this design.

There are at least two major architectural issues that have to be addressed by the interface developer when coding this kind of interface. First, a single window interface requires a software architecture that can effectively handle dynamic changes in the view hierarchy during runtime. I’ll address this issue in more detail in the third post on this topic.

The second issue that needs to be addressed is that in a single window interface design, a great deal of burden naturally falls on NSWindowController. In this type of setup, the application’s main window controller is responsible for handling a majority of the user interface. In other words, the interface code for an entire application, apart from a few dialog windows here and there, is expected to go into one single class. This code quickly becomes unmanageable and unmaintainable as the feature set changes and grows. It is natural to start to break this code up into logical groups of subcontrollers and to develop a system to manage and maintain these groups.

To accomplish this, many of us have already come up with our own “view controller” systems to extend our controller architecture. Apple has also started to address this issue by adding NSViewController to the Cocoa SDK in Leopard.

A standard view controller class is a great idea and welcome addition to Cocoa. One particular feature, the built-in memory management of objects in nib files, makes NSViewController a very attractive alternative to using a custom view controller. However, this class seems to have been left out of the controller layer of Cocoa’s MVC application architecture. Apart from being a subclass of NSResponder, there is no indication from the documentation or the class’s design that it is intended to be a part of the current controller architecture, but at the same time, it cannot be functional on its own. So where does NSViewController fit into a Cocoa app and how can developers use this class effectively to build a solid controller architecture in their applications?

NSViewController and the Cocoa MVC Architecture

AppArchitecture.jpg

For larger projects, specifically projects with single window interfaces, the view controllers form a significant portion of the software architecture and it would make sense for there to be a standard way to approach view controllers as a general design problem. Unfortunately, the Cocoa documentation doesn’t give developers any hint as to what that approach should be. There are some clues in NSViewController’s API about how you could patch a single view controller into a specific area of your current design, but nothing that suggests a holistic design strategy.

The conceptual documentation of Cocoa’s “Document-Based Application Architecture” hasn’t been updated yet to explain how the Cocoa engineers intend for us to incorporate NSViewController the current application architecture. For example, the section that describes the “Key Objects” in the architecture makes no mention of NSViewController, and because of that, the paragraphs on “Typical Usage Patterns” still suggest that:

If your document has only one window, but it is complex enough that you’d like to split up some of the logic in the controller layer, you can subclass NSWindowController as well as NSDocument. In this case, any outlets and actions and any other behavior that is specific to the management of the user interface goes into the NSWindowController subclass.

Clearly a single NSWindowController subclass isn’t going to manage the whole user interface for an application like iPhoto. This would be a perfect place to discuss the role of NSViewController.

I’ve given a lot of thought to the possibility that maybe it is better for Apple to leave this particular design decision to the developers. As I mentioned, the view controllers in an application can grow into a significant portion of the architecture and it is annoying when Cocoa’s designs clash with your own. However, if this is the case, what is the point of adding a view controller to Cocoa? Those of us that have our own view controller system design already have our own view controller class that works in that design. What is the incentive to use NSViewController instead of our own class if it doesn’t present a solution to the larger problem?

I’ve found from my own experience and from talking to other developers, that the design of a view controller system is the kind of design that tends to solve itself naturally within the current Cocoa MVC architecture. There isn’t much room for imagination when it comes to its most basic structure. If you ask developers how they organize their controllers, you’ll almost always get some variation of the same basic design: view controllers own and manage a list of subcontrollers and the window controller owns and manages the view controllers. It isn’t much different from the window and the view hierarchy. The window has a content view and the content view has a list of subviews which contain a lists of subviews, etc.

In fact, this particular relationship – the window and its views to the window controller and its view controllers – is very tight. The view controllers and the window controller build and manage the view hierarchy. The window controller has to add the view controllers’ views to the window’s content view. On top of that, the window controller needs to provide a way for the view controllers to enter the responder chain and, if there is a document, it should also give them access to that. It seems logical that the relationship between NSWindowController and NSViewController should exist by default. The view controllers are, after all, an extension of the window controller.

When programming a large, single window interface, the first enhancements a developer is likely to make to NSViewController, before they can effectively use it in their application, is to add a list of subcontrollers and implement the methods to manage the list. The next thing would be to establish some kind of relationship between this structure of view controllers and NSWindowController. These enhancements are enough to make NSViewController a key player in the current Cocoa controller archtitecture.

Taking the Plunge

The modifications to NSViewController that I mentioned above are simple enough for developers to make on their own. But there are certain caveats that come up in the implementation details that are directly related to Cocoa. These “gotchas” are not obvious until you start to test the design, but they also have to be dealt with before NSViewController can work effectively within the current controller architecture.

This is how I met Jonathan Dann on the Cocoa-dev list. Jonathan’s post was titled, “Correct use of NSViewController”. The title caught my attention because I had just finished my view controller design the week before. I was not too surprised to see that his question had to do with implementing the exact design I’ve described in this post. A few others chimed in with their solutions and it was very clear to me that this design is very obvious and that the issues in it were not unique to my implementation.

Jonathan and I continued our discussion off-list and decided that we would write about the experience we had with NSViewController. In the next post, he and I will describe the issues we came across when we tried to incorporate NSViewController into the Cocoa architecture and also provide our subclasses of NSViewController and NSWindowController as an example of how it might be accomplished.

To be continued…

Resources

Introduction to Document-Based Applications Overview

NSViewController Class Reference

NSWindowController Class Reference

NSViewController documentation bug report - rdar://problem/5794739

Tags: ,

5 Responses to “NSViewController, the New C in MVC - Pt. 1 of 3”

  1. Scott Stevenson Says:

    Great article. Have I mentioned I’m a fan? A couple of things:

    1. I’m glad you filed a request, because that means someone can evaluate the situation and figure out if/how it needs to be updated.

    2. It sounds to me like you have two separate requests here: documentation and API changes. I’d recommend filing these as separate radars because they would obviously go to different departments.

  2. Cathy Says:

    Thanks, Scott : )

    I’ll file another radar.

  3. Peter Hosey Says:

    Your feed-statistics plug-in mutilates the links in your feed.

    Here’s one of your links as I see it here in my browser:

    http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Concepts/OverviewDocArchitecture.html#//apple_ref/doc/uid/20000023

    And here it is as it appears in your feed:

    http://katidev.com/blog/wp-content/plugins/feed-statistics.php?url=aHR0cDovL2RldmVsb3Blci5hcHBsZS5jb20vZG9jdW1lbnRhdGlvbi9Db2NvYS9Db25jZXB0dWFsL0RvY3VtZW50cy9Db25jZXB0cy9PdmVydmlld0RvY0FyY2hpdGVjdHVyZS5odG1sIy8vYXBwbGVfcmVmL2RvYy91aWQvMjAwMDAwMjM=

    The only way to make that worse would be to run it through HugeURL. ☹

  4. Cathy Says:

    Peter. Thanks. I needed to see that. I wiill deactivate that guy.

  5. Steven Degutis Says:

    This was very informative! I often wondered what that little guy was doing hiding out in the documents and API, never quite had the time to experiment around with him either. I look forward to reading the next post from you two!

Leave a Reply