New in Leopard: Source lists!
[info]chanson
One of the great new features in Leopard is a standard way of supporting source lists — those blue outline views with a gradient highlight, like in iTunes, that provide an interface to some collections of objects.

These have become quite common in a lot of applications since their introduction in iTunes, and everybody does them slightly differently. Now, though, there's a simple way for applications running on Leopard to get the source list look and feel almost for free!

There's a new property added to NSTableView called selection highlight style. There are currently two possible values for the highlight style: Normal, the default, which gets you the regular look and feel and selection highlight behavior, and source list, which gets you not just source list-style selection highlighting, but also gets you the proper background color — whether you're in the foreground or the background — and for outline views, will also get you the proper indentation per level, the row height, and inter-cell spacing.

You can even set this property directly on your table or outline view in Interface Builder 3!

Of course, the obvious next question is "How do I get the small-caps look for section headers like in iTunes, Mail, and the Finder?" It's pretty simple! There are just a couple of methods you'll need to implement in your NSOutlineView delegate as described by Jim Puls in this message to the cocoa-dev list on October 26; conceptually, all you need to do is tell the outline view that your header items are group items — another new feature in Leopard — and then, when the cell containing them is displayed, adjust their string to be all-caps.

Unit testing Cocoa user interfaces: Cocoa Bindings
[info]chanson
About a year ago, I wrote about unit testing target-action connections for Cocoa user interfaces. That covers the traditional mechanism by which user interfaces have typically been constructed in Cocoa since the NeXTstep days. However, with the release of Mac OS X 10.3 Panther we've had a newer interface technology available — Cocoa bindings — which has presented some interesting application design and testing challenges.

Among other hurdles, to properly use Cocoa bindings in your own applications, you need to ensure that the code you write properly supports key-value coding and key-value observing. However, since the release of Mac OS X 10.4 Tiger, the necessary APIs have been available to easily do test-driven development of your application's use of Cocoa bindings, following a trust, but verify approach. (It's also been quite easy from the start to test your support for key-value coding and key-value observing, to ensure that your code meets the necessary prerequisites for supporting bindings. I can write more on this topic in another post if anyone is interested.)

The key to writing unit tests for Cocoa bindings is the -infoForBinding: method in AppKit's NSKeyValueBindingCreation informal protocol. Using this simple method, you can interrogate any object that has a binding for all of the information about that binding! It simply returns a dictionary with three keys:
  1. NSObservedObjectKey, which is the object that the binding is bound to;
  2. NSObservedKeyPathKey, which is the key path that is bound — in Interface Builder terms, this is the controller key path combined with the model key path, with a dot in between them; and
  3. NSOptionsKey, which is a dictionary of additional binding options unique to the binding. These are all of those additional checkboxes and pop-ups in the Interface Builder bindings inspector for setting things like a value transformer.
By specifying what this dictionary should contain for a particular binding, you can describe the binding itself and thus start doing test-driven development of your Cocoa bindings-based user interface. Note that all of the system-supported binding names — as well as the binding option names — are specified in <AppKit/NSKeyValueBinding.h> and are documented, too!

Let's take a simple example, like the one in last year's target-action example, of a window controller whose window has a static text field in it. The field should have its value bound to the name of a person through an object controller for that person. Assume that I've already created the test case and set up some internal methods on my window controller to refer to the contents of the window via outlets, and to load the window (without displaying it) in -setUp just like in the target-action example.

First, to see that my text field has a value binding, I might write something like this:
- (void)testPersonNameFieldHasValueBinding {
    NSTextField *personNameField = [_windowController personNameField];

    NSDictionary *valueBindingInfo = [personNameField infoForBinding:NSValueBinding];
    STAssertNotNil(valueBindingInfo,
        @"The person name field's value should be bound.");
}
Of course, this tells us nothing about how the binding should be configured, so it needs some fleshing out...

Let's check the object and key path for the binding.
- (void)testPersonNameFieldHasValueBinding {
    NSTextField *personNameField = [_windowController personNameField];

    NSDictionary *valueBindingInfo = [personNameField infoForBinding:NSValueBinding];
    STAssertNotNil(valueBindingInfo,
        @"The person name field's value should be bound.");

    NSObjectController *personController = [_windowController personController];
    STAssertEquals([valueBindingInfo objectForKey:NSObservedObjectKey], personController,
        @"The person name field should be bound to the person controller.");

    STAssertEqualObjects([valueBindingInfo objectForKey:NSObservedKeyPathKey], @"name",
        @"The person name field's value should be bound to the 'name' key.");
}
Not very exciting, and a little verbose, but it'll easily lead us through what needs to be set up in Interface Builder for this binding to work. If you want to cut down the verbosity, you can of course extract a method to do the basic checking...
- (BOOL)object:(id)object shouldHaveBinding:(NSString *)binding
            to:(id)boundObject throughKeyPath:(NSString *)keyPath
{
    NSDictionary *info = [object infoForBinding:binding];

    return ([info objectForKey:NSObservedObjectKey] == boundObject)
            && [[info objectForKey:NSObservedKeyPathKey] isEqualToString:keyPath];
}

- (void)testPersonNameFieldHasValueBinding {
    NSTextField *personNameField = [_windowController personNameField];
    NSObjectController *personController = [_windowController personController];
    
    STAssertTrue([self object:personNameField shouldHaveBinding:NSValue
                           to:personController throughKeyPath:@"name"],
    @"Bind person name field's value to the person controller's 'name' key path.");
}
If you're writing code that needs, say, a value transformer, it's a simple matter to extend this model to also check that the correct value transformer class name is specified for the NSValueTransformerNameBindingOption key in the binding options dictionary returned for NSOptionsKey.

You can even extract these kinds of checks into your own subclass of SenTestCase that you use as the basis for all of your application test cases. This will let you write very concise specifications for how your user interface should be wired to the rest of the code, that you can use to just walk through Interface Builder and connect things together — as well as use to ensure that you don't break it accidentally by making changes to other items in Interface Builder.

This is the real power of test-driven development when combined with Cocoa: Because you can trust that the framework will do the right thing as long as it's set up right, you simply need to write tests that specify how your application's interface should be set up. You don't need to figure out how to create events manually, push them through the run loop or through the window's -sendEvent: method, how to deal with showing or not showing the window during tests, or anything like that. Just ensure that your user interface is wired up correctly and Cocoa will take care of the rest.

CocoaHeads Silicon Valley at Apple on Thursday, April 12, 2007
[info]chanson
The next CocoaHeads Silicon Valley meeting will be on Thursday, April 12, 2007 from 7:30-9PM in the Hong Kong conference room at Apple. That's just inside the entrance to Infinite Loop 1, the main headquarters building at Apple's campus in Cupertino.

See the web site for details, directions, and the organizer's contact information.

R. Tyler Ballance will be talking about C#, Microsoft .NET 3.0 and Visual Studio.NET 2005 as someone who has used both platforms extensively. But don't worry, he's not pitching us on becoming a Microsoft developer! He'll be comparing and contrasting it with Objective-C, Cocoa, Xcode and Interface Builder — even covering some of what's coming in Leopard — and he may even cover what the Open Source community has to offer with Mono.

As always, we'll also be hanging out and talking about Cocoa in general, discussing new and cool things that have come up in the past month, and helping each other out. Join us!

Interface Builder helps you leverage MVC
[info]chanson
Kevin Hoffman, The .NET Addict's Blog: A NYC .NET Developer in Steve Jobs' Court - Day 1:
I took a step back and tried to figure out what the hell was going on. After a few minutes, I realized that Xcode was actually doing a really, really, really good thing. The vast majority of problems that arise from a poor separation of concerns between the GUI and the underlying code, model, and controller (if you even have such constructs in your app!) stem from the fact that you can double-click a button and immediately start writing code without thinking about the consequences of such a thing.

The NIB (stands for NeXTStep Interface Builder) file is a loosely coupled, standalone, user interface definition. It wouldn't make sense to double-click a button and immediately be taken to a code-behind. Instead, you have to create a controller class, and then ctrl-drag from the button to the controller and then pick the outlet you're going to use (something like click: or calculate:). To me, as a huge fan of the MVC pattern, this makes perfect sense. And it seems so elegant in its simplicity, and so incredibly cool in the fact that it is truly enforcing good design simply by the way the IDE works.
Kevin sees very clearly what sometimes takes people quite a while to realize: The design of Interface Builder and the design of the Cocoa frameworks go hand-in-hand to help you best leverage a model-view-controller architecture in your application and thus create something maintainable over the long haul. Interface Builder isn't just a "form painter" for a rapid application development environment that's discarded by the "more serious" developers — it's a critical piece of technology that every Cocoa developer can leverage to improve their application's design.

Unfortunately I can't say a whole lot about Leopard and its improvements to Interface Builder here. I can, however, point you to the Xcode 3.0 page on Apple's Mac OS X Leopard Sneak Peek site and the Leopard Technology Series for Developers at the Apple Developer Connection, which includes a great high-level Developer Tools Overview.

Leopard Developer Tools Overview
[info]chanson
There's a Leopard Developer Tools Overview now at the Apple Developer Connection!
The developer tools in Mac OS X Leopard are crafted for one mission: to enable you to create amazing applications. Offering a streamlined workflow, Xcode 3.0 helps you develop your applications faster than ever. The all-new Interface Builder lets you build awesome user interfaces that take full advantage of Leopard's capabilities. The new language features in Objective-C 2.0 speed up your development cycle. The innovative new Xray brings the ability to visualize your application at runtime in a way that's never before been possible. And, the brand-new Dashcode makes it a snap to create elegant and powerful Dashboard widgets.
It's the second article in the Leopard Technology Series for Developers, and boy is there a lot of meat there!

The article covers a whole lot of tools: Xcode 3, Interface Builder 3, the extremely innovative new Xray performance tool, and Dashcode, Apple's environment for creating Dashboard widgets using HTML, CSS, and JavaScript. There's a lot of coverage of Xcode enhancements including code folding, improved syntax coloring, inline display of errors and warnings, inline editing of breakpoint conditions, and mouse-over inspection of variables while debugging.

Of perhaps even more interest than the new tools to Cocoa developers will be some information about new language features in Objective-C 2.0 including fast iteration of collections using for ( … in …) syntax and properties that eliminate the tedium of implementing accessor methods and streamline accessor syntax.

Check it out!

Unit testing Cocoa user interfaces: Target-Action
[info]chanson
It's really great to see that a lot of people are adopting unit testing for their projects and dramatically improving their quality. Test-driven development and agile development methodologies built around it are really taking off. However, a lot of people still feel that their user interface is difficult to test through code, and either requires a capture-playback tool or requires a different design approach based heavily on interfaces/protocols to get right.

In last year's post Trust, but verify. I tried to dispel some of the mystery of testing your application's user interface when using the Cocoa frameworks. However, I've still had a lot of (entirely well-justified!) requests for examples of how to put it into practice. So here's a simple example of what I'd do to write a unit test for a button in a window that's supposed to perform some action.

First, when implementing my window, I'd follow the standard Cocoa pattern of having a custom NSWindowController subclass to manage my window. This window controller will have an outlet connected to each of the views in the window, and will also wind up with a private accessor method — used only within the class and any subclasses, and in testing — for getting the value of each of its outlets. This design flows naturally from the test which I would write to specify that the window should contain a button. First, here's the skeleton into which I'd put tests:
// TestMyWindow.h

#import <SenTestingKit/SenTestingKit.h>

@class MyWindowController;

@interface TestMyWindow : SenTestCase {
    MyWindowController *_windowController;
    NSWindow *_window;
}
@end

// TestMyWindow.m

#import "TestMyWindow.h"
#import "MyWindowController_Private.h"

@implementation TestMyWindow

- (void)setUp {
    // MyWindowController knows its nib name and
    // invokes -initWithWindowNibName: in -init
    _windowController = [[MyWindowController alloc] init];

    // Load the window, but don't show it.
    _window = [_windowController window];
}

- (void)tearDown {
    [_windowController release];
    _window = nil; // owned by _windowController
}

@end
That's the infrastructure into which I'd put my other test methods for this window. For example, I'll want to specify the nib name for the window controller and ensure that it actually knows its window:
- (void)testNibName {
    STAssertEqualObjects([_windowController windowNibName], @"MyWindow",
      @"The nib for this window should be MyWindow.nib");
}

- (void)testWindowLoading {
    STAssertNotNil(_window,
      @"The window should be connected to the window controller.");
}
Now let's check that I have a "Do Something" button in the window, and that it sends an action directly to the window controller.
- (void)testDoSomethingButton {
    // _doSomethingButton is a private method that returns the button
    // conected to the doSomethingButton outlet
    NSButton *doSomethingButton = [_windowController _doSomethingButton];
    
    STAssertNotNil(doSomethingButton,
      @"The window should have a 'Do something' button.");
    
    STAssertEqualObjects([doSomethingButton title], @"Do Something",
      @"The button should be titled accordingly.");

    STAssertEquals([doSomethingButton action], @selector(doSomething:),
      @"The button should send -doSomething: to its target.");

    STAssertEquals([doSomethingButton target], _windowController,
      @"The button should send its action to the window controller.");
}
You'll notice something I'm not doing in the above: I'm not simulating interaction with the interface. This is the core of the trust, but verify approach to unit testing of your user interface.

I can trust that as long as I verify everything is hooked up properly that Cocoa will cause the button to send its action message to its target — whether it's a specific object or, if the target is nil, the responder chain — whenever the button is clicked while it's enabled and not hidden. I don't need to simulate a user event, and I don't even need to display the interface while running the unit tests. All I need to do is inspect, through code, that everything is wired up correctly.

Note that I can do way more than the above in testing my interface design, too. For example, I can ensure that the control layout is correct according to what my interface designer has specified, by checking bounding rectangles for example. But testing only the functionality of my interface has significant advantages, too. For example, it doesn't matter if I wind up using a custom kind of button to achieve exactly the kind of look and feel or behavior I need. It doesn't matter if I wind up changing the layout in response to feedback. No matter what I do, I'll know that functionality won't accidentally break while I'm messing around in Interface Builder — even if I completely rip out my interface and replace it with a new one!

This approach can also be used for testing Cocoa bindings using the -infoForBinding: method that was introduced in Mac OS X 10.4 Tiger. I hope to write up a post soon on how to approach Cocoa bindings using these same techniques, but it should be fairly straightforward given the above and the above documentation.

Update: I've struck through the check of the button's title above, because you may or may not want to do that. For example, if you're primarily running your unit tests against your development localization, you may want to put it in. But if you want to run your unit tests against a localized build of your application, you'll probably want to avoid checking a localized title against an English string. A "have your cake and eat it too" strategy might be to keep a variable somewhere in your application that can be used to selectively disable checks of only localized strings.

Update July 7, 2007: I've finally written a post, Unit testing Cocoa user interfaces: Cocoa bindings, on how to write tests for Cocoa bindings. Now there's no excuse for not doing test-driven development of your Cocoa user interfaces!

ADC Video Tutorial on Core Data
[info]chanson
Yesterday, the Apple Developer Connection posted a new video tutorial by Wolf Rentzsch, Building a Sample Core Data Application.

If you're at all interested in Cocoa and Core Data development on Mac OS X, you should definitely check it out!

"Enterprise" thought leadership?
[info]chanson
David Heinemeier Hansson, creator of Rails at 37signals, takes James McGovern — some Java/J2EE author — to task for his über-lame rant against Ruby in the Enterprise in a great post titled Boy, is James McGovern enterprise or what!

So by Enterprise, Architect, and Enterprise Architect standards, this gent must be the top of the pop. Thus, allow me to make this perfectly clear: I would be as happy as a clam never to write a single line of software that guys like James McGovern found worthy of The Enterprise.

If Ruby, Rails, and the rest of the dynamic gang we're lumped together to represent, is not now, nor ever, McGovern Enterprise Ready™, I say hallelujah! Heck, I'll repeat that in slow motion just to underscore my excitement: HAL-LE-LU-JAH!

With that out of the way, we're faced with a more serious problem. How do we fork the word enterprise? The capitalized version has obviously been hijacked by McGovern and his like-minded to mean something that is synonymous with hurt and pain and torment.

Indeed, McGovern's rant reads more like a parody of a rant than the real thing:
13. Lets say there is a sixteen week project and the productivity stuff was true and Ruby could save me an entire three weeks which would be significant. Since Ruby is a new vendor and not represented by existing vendors I already do business with, do you think that I will spend more than three weeks in just negotiating the contract?
Yes, because there is some vendor out there named "Ruby that you need to sign a contract with before you can begin a project.

Despite his claims to be agile, McGovern obviously doesn't know the first thing about agile development. People come first, sure, but agile development doesn't say that tools aren't important. Not using good tools makes it harder for good people to do good work.

That's why I love developing software for Mac OS X and why I love helping people develop software on Mac OS X: We have great tools like Cocoa, Core Data, Interface Builder, OCUnit, WebObjects, and Xcode, and these can be used by great developers to do great things.

Core Data: Generating an interface for an entity
[info]chanson
The new Core Data framework and Xcode 2 modeling tools in Tiger are an extremely powerful way to develop great end-user applications quickly. You can even easily generate a human interface for your application that will let you work with its data model with little to no code.

To generate an interface, create an empty window in Interface Builder and make sure you'll be able to see it with Xcode in front. Switch to your model in Xcode. Then just option-drag the entity you want an interface for into your window. Interface Builder will ask you whether you want an interface for one or many instances of that entity, and then generate a basic form-style human interface for all of the attributes and to-one relationships in that entity.

This generated interface isn't a special monolithic "NSCoreDataControl" or anything of the sort. it's composed of standard Cocoa controls that wired to standard Cocoa controllers via bindings. If your nib file's owner is set to be an instance of NSPersistentDocument or a subclass, Interface Builder will even bind the controllers' managed object contexts to the document's.

If you just want to create controllers rather than full interfaces, or if you want to update the controllers in your nib file with the latest definition of your entity, drag the entity from your model straight to your nib's document window. (That's the one with the tabs for classes and instances etc.)

Note that none of this, none of this requires generating or writing code. You can create a new Core Data Document-based Application from the project template, create a data model for it in Xcode, create an interface for it in Interface Builder, and then build and run it. You can create, save, load, and manipulate documents and even undo and redo changes and avoid saving invalid data with no code.

Oooo, XAML and WinFX, what a concept!
[info]chanson
So Windows Longhorn includes a new .NET application framework called WinFX, code-named "Avalon."

Turns out I was overly optimistic in my estimation of what Avalon was. It turns out Avalon is just a system for specifying your application's human interface in an XML-based language, XAML, and even specifying what actions in your code will be invoked by different interface elements. And then, get this: You generate C# code from this that actually creates your interface!

Gosh wow, golly gee! You mean I can use XML to drive a code generator? Ooo! Where do I sign up?

Why the hell does it need to generate code just to create an interface? Why the hell does it need to generate code just to associate a control with an action method? What decade are we living in again? Interface Builder on NEXTSTEP was doing this stuff right in 1988. Why are people acting like Longhorn's getting it marginally less wrong than previous Windows frameworks is such a big deal?

There's even a system like XAML available for Cocoa: GNUstep Renaissance. Renaissance lets you specify your interface in an XML file, too, and has for quite a while. (Nicola Pero first released it on December 26, 2002.) The big difference is that with Renaissance, you just load this "gsmarkup" file at run time and it generates the interface and binds it to your objects right then!

What's more, it includes a layout manager system similar to Java's for automatic interface layout. So you don't even need to specify sizes of controls, you can just let the layout manager handle everything.

Here's what a simple gsmarkup looks like (taken from the Renaissance Tutorial):
<gsmarkup>
  <objects>
    <window title="This is a test window" closable="no">
      <button title="Print Hello!" action="printHello:" target="#NSOwner" />
    </window>
  </objects>
</gsmarkup>
This gsmarkup file specifies an NSWindow with no close box and the title "This is a test window", which contains an NSButton titled "Print Hello!" that sends -printHello: to the object that owns gsmarkup (set when the gsmarkup is loaded). Note that you don't have to specify the size of the button, where in the window it is, etc. You can if you want (or need) to, you just don't have to. And if you don't specify a target for a control, its target is assumed to be nil (the First Responder).

You can use id attributes in a markup to name objects and then refer to them using the standard reference (#foo) notation to wire them together within the same gsmarkup file.

And here's something even cooler: When a gsmarkup is loaded, an associated strings file is also loaded if one exists. This makes it very easy to translate gsmarkup-based applications into other languages. You don't even need to change the gsmarkup (especially if you're using layout managers) — you just have to supply a strings files for the other languages!

And possibly the best part: Renaissance works on both GNUstep and Mac OS X. You only need to maintain a different menu structure between the two; for everything else, you can use a single set of markup files (assuming you're using layout managers). One codebase, one interface spec, multiple platforms.

For more information, check out the Renaissance Manual.

More about Panther Cocoa
[info]chanson
Panther shipped!

That means I can go into more detail about what I'm talking about at the CAWUG meeting on Tuesday.

Here's the deal: In Panther, Cocoa includes a ton of new features. Most importantly, Panther Cocoa includes a new AppKit class named NSController.

In Model-View-Controller terms, Cocoa has historically been great for building model objects with FoundationKit and for building view objects with AppKit. But you've generally had to build all of your controller objects from scratch with FoundationKit. This isn't a problem per se but it does mean you have to do work. For instance, you had to write a data source object have an NSTableView display some data.

Now, with Panther Cocoa and NSController you can very easily bind view objects to your data model directly, with no code, right in Interface Builder.

It does this using some technology built on top of Key-Value Coding. Key-Value Observing lets one object watch for changes in an attribute of another and Key-Value Binding lets the values of attributes in two objects be dependent on each other (change one and the other changes).

On Tuedsay at CAWUG, I'm going to demonstrate how all this fits together.

But wait, there's more!

Apple also did quite a bit of optimization work in Panther, including optimizations to how NSView drawing works.

They've even included a new class in FoundationKit called NSSortDescriptor that represents — surprise — a way of sorting a collection! It's pretty much an equivalent of my BDSortOrdering class, which was just a reimplementation of the Enterprise Objects Framework's EOSortOrdering class.

I'll also be talking about some of the other major additions to Cocoa in Panther. There's a lot of cool stuff to cover! Join us! It'll be fun!

Next CAWUG Meeting: Cocoa changes in Panther
[info]chanson
I'm going to be talking at the next Cocoa and WebObjects User Group (CAWUG) meeting. It's at 7PM next Tuesday, October 28, at the Apple Store North Michigan Avenue.

Alex Johnson of Site9 maintains an iCal calendar (subscribe via iCal).

Here's the summary of Chuck's IOKit talk and what I'm allowed to say about my talk. I'll post more details tonight about what I'll actually be covering, after Panther's officially released.

IOKit by Chuck Remes

Chuck has worked on an ethernet driver for the DEC Tulip chip set and will discuss IOKit. IOKit provides all the basic services to develop a hardware or software driver for darwin (or OS X). It is a powerful toolkit that let's the programmer bring all the power of OOP to the world of drivers, allowing such things as subclassing, method overload, and driver stacking. This presentation will provide a high-level 45 minute overview of some of its basic features and principles.

Xcode & new Cocoa features in Panther by Chris Hanson

Chris Hanson of bDistributed.com will go over some of the additions to Cocoa included in Panther, as well as the new Xcode IDE and the updated Interface Builder.

PSIG tonight
[info]chanson
I'm going to be presenting at the Northwest of Us Programming SIG (PSIG) tonight about the bDistributed.com BDControl and BDRuleEngine frameworks, and demonstrating a rule-based application. I wrote the frameworks and they're Open Source under a BSD license; I encourage every Cocoa developer to check them out, since they can make your life easier.

I'll also give a quick overview of how Interface Builder palettes work, and a palette I've created that acts as a table data source and lets you wire up an object to a table without writing any code.

The full meeting announcement is here on Jon's weblog: PSIG 68: Thursday, September 4th, 2003

For those who don't know, the Northwest of Us is a Macintosh User Group in the northwest suburbs of Chicago, IL. The PSIG meets at the NWoU office in Palatine, Illinois a couple blocks northwest of the intersection of route 53 and route 14.

A note for anyone creating Interface Builder palettes
[info]chanson
If you're creating an Interface Builder palette, you need to wire up the controls in your Inspector nib file to send "ok:" to File's Owner (your IBInspector subclass).

If you don't do this, you may find yourself wondering why your changes aren't actually persisting...