Monday, March 15, 2004
cocoa 0wns me

Yeah yeah yeah, long time no write. I'm a bad person. Shutup.

When learning how to program a new system, I like to write lots of small programs that do one or two tasks. Small programs with just enough code in them to learn to do basic simple system tasks.

In this case, the task was to learn how to open a window in Cocoa. Which should be, and is, simple. But I hadn't gotten it to work correctly yet.

Oh, I finally did though. After a week of spending five minutes here, and five minutes there on the problem, it finally worked itself out this weekend.

It was all my fault. As usual.

In Cocoa, you use Interface Builder (IB) to build any GUI elements. You lay out actual objects, and then IB freeze-dries them and writes them into a file called a nib file (NeXT Interface Builder, betraying the roots of Cocoa).

The standard way to open a window is to instantiate an NSWindowController object, have it load the nib file, and then get a reference to the window from the window controller, and send the orderFront: message to it. Very simple. You just load up the freeze-dried objects, and tell them to make themselves visible.

For some reason, I couldn't seem to make that happen.

I farted around with IB, found a checkbox for "Display Window at Launch", checked it, and saved the nib. Now the windows open when I run my code, but that seemed wrong, because it meant that I couldn't load the nib file in the background and make it appear when I wanted it to. It would always appear when the nib file was loaded by the window controller. I thought I may have found the answer, but it just didn't sit right.

As I said, I was pounding on the code again this weekend, looking to figure out what I did wrong.

I did some debugging, and found out that when I was trying to get a reference to the window from the window controller after I had loaded the nib, I got nil. Then the next thing my code did was send a message to the window, or in my case, nil. Guess what -- in Objective-C, nil responds to all messages, and for those that make no sense, it just FAILS SILENTLY.

Fuck me. It was my fault, but when presented with an opportunity to point out what sort of idiot I am, the system instead just hides it, preferring to go for the bigger result, implanting in me the belief that I do not really understand what the hell is going on.

Why did the window controller have nil instead of a reference to the window? Because I never told IB to make a reference to the window available to the object loading the nib. Which, when you grok the whole idea behind nibs, makes a certain sort of sense. At least now it does. Before the weekend I just figured that I was an idiot.

To sum up, the bit I left out was telling IB that the "File Owner" object was an instance of NSWindowController, and that its "window" slot referenced the window in the nib file. Once that last connection was made, everything worked according to the documentation.

Bastard code.

9:48:18 AM    comments ()  trackback []