Clozure CL and Xcode 4
Update: Manually modifying the Homebrew formula for Clozure is unnecessary as of November 2011.
I just learned about Clozure CL, a Common Lisp implementation with a
very friendly bridge for Cocoa. The idea of using Lisp to write
pseudo-'native' apps for OS X intrigued me, so I modified my
Homebrew's formula (changing 1.6 to 1.7 in the URL and changing
the MD5 checksum to 4f7d8c48abc9355c69946ef125fa2aa5 and installed
it. Getting it into SLIME was no issue, and soon I was working on
reproducing some of the example projects. I was using a tutorial from
within Clozure's contrib directory entitled Cocoa Interfaces Using the Apple Interface Builder and Clozure Common Lisp, written by
Dr. Paul Krueger.
This is where I ran into problems. The general gist of the tutorial (creating a window that takes two inputs, and sums them when a button is pressed) is that the interface can be designed in Apple's Interface Builder, and the backing code written in Lisp. Fair enough. Except Interface Builder really doesn't exist anymore. It has been rolled up into Xcode 4, a component that works seamlessly with the IDE itself. I don't begrudge Apple for improving their software's workflow; in fact, I applaud it. The trouble is that one of the steps the tutorial relies on no longer works the same way.
My understanding of Cocoa is a little spotty so I will explain it the best that I can. Objective-C incorporates message-passing-style object-orientation, and one of the ways it uses this to great effect is by creating delegates of components of the UI to send and receive different messages from. Since the instance that interacts with the UI controls must exist before the UI itself gets loaded, a representation of that instance, called "File's Owner", exists in the Interface Builder. In Xcode 3, the exact object type of the File's Owner did not need to exist in code, because a mechanism existed for generating the object you described when switching between Interface Builder and the Editor.
In Xcode 4, no such mechanism exists. Instead, you can literally drag the connection from your UI into a source code file, and the connections (called 'actions' or 'outlets' depending on their function) will be autowritten for you. A nice touch, if you actually are working in a full-fledged Cocoa project.
You kind of have to do something like that from now on when creating nibs for Clozure-CL projects, as far as I can tell.
In the example of the simplesum project in the above PDF, after
creating your UI, create a new 'Cocoa Objective-C class', with
implementation and header files, and call it SumWindowOwn. In its
header file, you'll be handwriting the connections you'd like.
Where the PDF says:
In the Class Outlets part of the window click the "+" button to add a new outlet. Edit the name to be "input1" and the type to be NSTextField.
We will instead add a line of code in the @interface of SumWindowOwn:
@property (assign) IBOutlet NSTextField *input1;
Where the PDF says:
Click the "+" button and add a new action. Edit the "MyAction1:" name that is generated and change it to "doSum:".
We will instead add a function interface:
- (IBAction)doSum:(id)sender;
Do this for the other outlets in the tutorial, and then you can
CTRL-drag the UI controls onto the lines you just wrote. Not
between, or after, literally onto.
At this point I was able to load the nib using iu:loadnib without
issue.
I recognize some or all of my explanation above may be vague, oversimplified, or flat-out wrong. I will happily consider corrections to my understanding of the situation.