Archive for October, 2008

Working without a nib, Part 7: The empire strikes back

Monday, October 20th, 2008

I recently received an email from Steve Jobs. He told me that he has read all of my blog posts. I found this ridiculous, so I replied, “You’re full of it!” Shockingly, he wrote back. “Actually,” he said, “all of the new apps of the past few years are nibless.” He then described the Apple-sanctioned technique of writing a nibless application.

In previous posts of this series, I was forced to use obscure workarounds such as +[NSObject poseAsClass:] and method_exchangeImplementations() to prevent NSApplicationMain() from trying to load a nib. Jordy Rose of Belkadan Software suggested to me that the easiest way to prevent NSApplicationMain() from trying to load a nib would be to avoid calling NSApplicationMain() at all. Instead, you would just call -[NSApplication run]. However, I was worried that NSApplicationMain() might do something else important (like phone home to get permission to launch). We don’t know, because we don’t have the source code.

I’m still waiting for the source code, but Steve did indicate that it was safe to skip NSApplicationMain(). Thus, there’s no need for tricksy runtime manipulation, except perhaps to prove your mad programming skills. Mad, that is, in the sense of having worn one ring for too long. Steve also affirmed that our call to -[NSApplication setAppleMenu:], a method that Apple removed from the API, will continue to work until there’s a replacement API. Indeed, Apple is working on some kind of replacement. Excellent! /me plays air guitar. So if you’re counting at home, it’s now (1) Exchange support and (2) Nibless support.

He didn’t mention the Open Recent menu, so it appears that my ugly hack is still required for non-document-based apps. This cannot be considered part of the Apple-sanctioned technique, though it is sanctioned by me, which is more desirable, because my approval comes in seven delicious flavors. I’ve updated Nibless for Leopard in light of Steve’s revelations and am making version 2.0 available for immediate download. This is major progress, because it already puts me two versions ahead of VLC.

So long, Steve, and thanks for all the fish!

Cocoa memory management for smarties, Part 3: accessors

Sunday, October 5th, 2008

This post is not over until Minnesota Fats says it is, or until I figure out why he played in Iowa. In the meantime, let’s talk about getters and setters. A setter is distinguished by the prefix set, while a getter is distinguished by not having the prefix get. Got it? Getters and setters come in pairs; collectively, they are commonly known as accessor methods, less commonly as American Airlines or pocket rockets.

Accessor methods provide encapsulated access to an object’s instance variablesinstancvariabls for short. If your instancvariabl is an Objective-C object (in Freudian terms, an id), your accessors should almost always look like this:

-(id) thing
{
	return [[_thing retain] autorelease];
}

-(void) setThing:(id)aThing
{
	if (_thing != aThing)
	{
		[_thing release];
		_thing = [aThing retain];
	}
}

You can copy rather than retain in setThing: if the class of aThing conforms to <NSCopying>.

It may seem redundant to [[_thing retain] autorelease] in thing, but this has an important purpose. (A special purpose, if you will, which you’ll want to use every chance you get.) Simply returning _thing in thing does not suffice, as the following code demonstrates.

1 id something = [myObject thing];
2 [myObject setThing:nil]; // Clear out the thing.
3 [something doSomething];

In line 3, your app will go boom. I’ve seen it argued (on bathroom stalls, for example) that the caller ought to [[myObject thing] retain] on line 1 because of this possibility, but that’s simply not the caller’s responsibility. It’s an implementation detail of myObject that thing returns an instancvariabl which setThing: releases. Moreover, the caller could inadvertently call setThing: by calling some other method that calls setThing: rather than by calling setThing: directly. With [[_thing retain] autorelease], thing ensures that _thing will not be deallocated in the caller’s scope (as long as the caller doesn’t do anything stupid, like call out Minnesota Fats).

No discussion of accessors is complete without talking about thread safety. In order to write thread-safe accessors, you should first drink a bottle of whiskey. This is required because writing thread-safe accessors is a fool’s errand. Don’t do it. Don’t try it. Don’t even think about. Redesign your code to avoid the need for thread-safe accessors. If you feel you must, however, then you should acquaint yourself with Technical Note TN2123, because you’ll find yourself referring to it frequently. It’ll be like a nightmare, just getting (and setting) worse and worse. But at least the salad dressing will be good.