Cocoa Nibs

NIB files (or just Nibs) are, loosely speaking, Interface Builder’s save format. Having used “GUI builder” tools before, it was easy to think of them as descriptions of window designs, but they’re actually slightly different.

Nibs are just arbitrary collections of Objective-C objects — UI widgets or otherwise — serialised to disk. You can create any object instances you want in a Nib file and they’ll be unserialised when the Nib loads. As well as creating them, you can configure many of their member variables, and set up links between them so they can find each other at runtime (see Actions and Outlets, explained previously).

(In XCode 3.0, IB saves to XIB files. These are the same thing, but using XML stored in a single file, whereas Nibs are actually folders containing multiple files in proprietary formats. Apparently the change is to make them play nicer with source-control. Once you click Build in XCode 3.0, they get compiled to Nibs anyway, so I’m just going to keep calling them Nibs for now.)

There were some aspects of Nibs that were confusing to me when I started out. The ‘First Responder’ proxy object was one, but we’ve talked about that already. The ‘File’s Owner’ was another. This is another placeholder; anything you configure involving the File’s Owner is noted for future reference, but nothing actually happens until the Nib is loaded. The Cocoa function to load Nibs takes an owner pointer as a parameter, and this will be the recipient of any Outlet connections, Actions, etc you set up linked to File’s Owner.

If you load a Nib manually, it’s entirely up to you what you pass here; but most often Nibs are loaded by Cocoa itself, when the application starts up. In this case, the File’s Owner depends on the kind of application and the use the Nib will be put to. The default Nib, containing the main menu, is owned by the application itself. In some applications this might be the only Nib, but document-based applications keep the document window in a seperate Nib, and load multiple copies — each of these being owned by a different Document object.

In terms of data structures, a Nib is an array of “top-level objects” (these are the items visible in the Nib document in Interface Builder). Some of those top-level objects are just stand-alone objects, but many are containers: windows, views, toolbars, menus. These can be double-clicked in IB to open them, at which point you can drag out items from the Library palette and drop them into place. I’m not going to give an IB tutorial here; you really need to just sit down and fiddle with it. Since some of the items you drag out can themselves contain other items, the end result is a tree, rooted in the Nib’s top-level object array.

When you load a Nib, you can look through that array, and walk that tree, but mostly it’s enough that it exists, holding references to the items inside it, keeping them from being garbage-collected. Writing an app, you largely ignore these implementation details, and focus instead on the objects inside and their interconnections — most of those connections being set using Outlets in IB, rather than mucking around with the Nib’s object graph yourself.