Abusing Objective C With Class

April 12th, 2007

Dynamic messaging is one of the nifty features of Cocoa and Objective-C programming on the Mac. You don’t have to know which class, or even which method your code will call until runtime. The feature is utilized a great deal by the delegation pattern employed by most standard classes in AppKit. For instance, when a window is threatening to close, Apple yields the final decision making to a delegate method, if present:


- (BOOL) windowShouldClose:(id)sender;

If you implement this delegate method and return NO for a particular window, then the user’s attempts to close it are thwarted (hopefully because you just did something friendly like ask them if they were sure or not).

If we’re agreed that delegation and dynamic messaging are a good idea, we should be prepared to use them in our own code as well. Let’s say we’re writing a custom class where delegation of this kind would be useful. We’d like to be as much like Apple as possible, to further solidify the patterns that we all use on a regular basis.

My example application is a coffee maker, and it makes coffee at regular intervals unless the delegate method believes it should not:


- (BOOL) coffeeMaker:(RSCoffeeMaker*)theMaker
	shouldBrewForScheduledDate:(NSDate*)scheduledDate;

What must the code in the coffee maker do in order to satisfy this contract? The “scheduledBrewTimerFired:” method might look something like this:


- (void) scheduledBrewTimerFired:(NSTimer*)brewTimer
{
	BOOL shouldBrew = YES;
	
	// Give the delegate a chance to reject
	SEL delSelector = 
		@selector(coffeeMaker:shouldBrewForScheduledDate:);

	if ((mDelegate != nil) &&
		([mDelegate respondsToSelector:delSelector] == YES))
	{
		shouldBrew = [mDelegate performSelector:delSelector
			withObject:self
			withObject:[brewTimer fireDate]];
	}
	
	if (shouldBrew == YES)
	{
		//...
	}
}

Nifty, right? Yes, nifty. But wrong. What’s the problem? It’s that line where performSelector is called. If you have as many warnings turned on as you should, you’ll see something along the lines of “warning: assignment makes integer from pointer without a cast.” The reason? The performSelector method returns an “id”, not a “BOOL”. We’re expecting magic to happen here, and those of us who grew comfortable with the nuances of PowerPC-based calling conventions have seen magic happen here more often than is healthy.

By violating the function prototype for performSelector, we’re robbing the compiler of its ability to accurately produce assembly code that retrieves the BOOL return type correctly. That means we’ll get the wrong answer some percentage of the time, where that percentage is determined by the degree to which BOOL and id return types are handled differently on the platform.

My first instinct in addressing this problem was to go down a layer. Surely if performSelector is using an unsatisfactory prototype, I could just drop down to objc_msgSend and handle the messaging myself. But alas! The lower-level function also returns an id. At this level, there are some special functions such as objc_msgSend_stret, which messages an object and returns a structure, but there isn’t a handy objc_msgSend_boolret for our convenience.

So what’s a conscientous developer to do? I was lucky to discover a mailing-list thread, in which the answer to this question was beautifully outlined by Greg Parker of Apple. Credit also goes to Rosyna of Unsanity, for asking the question that led to Greg’s answer. Rosyna later expressed appreciation in a follow-up post.

So what’s the trick? In order to get the freedom of dynamic messaging combined with the complete cooperation of the compiler, we need to define a custom function pointer. This points to the same address in memory as the objc_msgSend function, but is defined with a differing prototype. This way we get the message delivery functionality of the Objective-C runtime, while letting the compiler in on the fact that the method being messaged will in fact return a BOOL typed response.


#import <objc/objc-runtime.h>

- (void) scheduledBrewTimerFired:(NSTimer*)brewTimer
{
	bool shouldBrew = YES;
	
	// Give the delegate a chance to reject
	SEL delSelector = 
		@selector(coffeeMaker:shouldBrewForScheduledDate:);
	if ((mDelegate != nil) &&
		([mDelegate respondsToSelector:delSelector] == YES))
	{
		// Give the compiler a clue - courtesy of Greg Parker
		BOOL (*MyMagicSender)(id, SEL, id, id) = 
			(BOOL (*)(id, SEL, id, id)) objc_msgSend;

		shouldBrew = MyMagicSender(mDelegate, delSelector,
			self, [brewTimer fireDate]);
	}
	
	if (shouldBrew == YES)
	{
		//...
	}
}

Nifty, right? And correct, too. Enjoy!

Update: Paul Kim via chat, and Jan Van Boghout in the comments below each noticed a flaw in my contrived example. Since I already know the selector I’m planning to call, I could just define it explicitly with a regular Objective-C method prototype. Then the compiler would know exactly how to generate the code if I called the delegate directly:


shouldBrew = [mDelegate coffeeMaker:self
	shouldBrewForScheduledDate:[brewTimer fireDate]];

That’s true, and it’s a fault in my overly-contrived example. But imagine a more dynamic scenario, where the prototype of the method is known, but not the selector. For instance, if the class offers clients the ability to specify a selector:


- (void) scheduleBrewingAtDate:(NSDate*)brewDate
	withBrewDelegate:(id)brewDelegate
	withDelegateSelector:(SEL)delSel;

Are You Feeling Lucky, Punk?

April 11th, 2007

In the years since I first started developing FastScripts, all manner of keyboard-shortcut type solutions have popped up, including the enormously ambitious Quicksilver, and the refined, trigger-action-oriented Butler.

But some of us still appreciate FastScripts for its simplicity. Put scripts in the standard Apple-location, cmd-select them from the FastScripts menu, and assign a keystroke. FastScripts could be improved in some important ways, but it’s been in “stable and revered” mode for years now, which has made it a reliable tool for people to recommend to others. I think it’s easy to recommend because it does exactly what it says it will do, and little more. You don’t need to join a FastScripts cult or change your entire workflow to get some use out of it!

Michael Tsai recommends it in the manual to his BBAutoComplete product. I see frequent referrals from Quark and InDesign forums, where running scripts efficiently is a major part of the creative and production process. It’s gratifying to know that FastScripts has become a part of the productive environment for so many people.

But sometimes people just use it because they feel lucky. Christopher Biagini shares his I’m Feeling Lucky script, which performs a simple but useful task. It asks you for a phrase, then it does the Google search for you, then it takes you straight to the “I’m Feeling Lucky” link. I clicked the handy “open it directly” button which worked like a charm to bring it to Script Editor. Then saved it to my Scripts folder and assigned a keystroke. Nifty! And a lot lighter-weight than Google Desktop :)

Go ahead, make my day. Give FastScripts a try!

Future Posting With MarsEdit

April 9th, 2007

From time to time people ask for a feature in MarsEdit that would allow scheduling of posts for future publication. While I can appreciate the desire for such functionality, the drawbacks to implementing it on the client-side are numerous. To schedule a future post, MarsEdit or a custom tool from MarsEdit needs to run in the future, at a precise time specified by the user.

Launchd and other system scheduling services make this task less formidable, but it’s still not exactly something I can whip up overnight. Fortunately, some publishing systems treat posts with future dates as unpublished, and automatically change their state to published when the specified date arrives. WordPress in particular definitely supports this. To see if your blog supports it, next time you’re publishing a post try setting the date to just a few minutes in the future. From the Post menu, select “Edit Date,” and enter a future time:

I am writing about this because I suspect many people don’t know about this really cool feature. I didn’t know about it myself until very recently. I was motivated to research it when Guy Kawasaki asked about the possibility. He confirmed that the trick works with his (excellent) TypePad-based blog, too. [Update: I believe the TypePad functionality may have only appeared to work. I have since learned that TypePad doesn’t seem to support this the way we had hoped.]

For any WordPress users who are curious, the functionality in that system is based on a nifty general-purpose “cron-like” service built-in to WordPress 2.1 and later. This allows the system and plugins to schedule future actions for a variety of purposes, including future posting. Glenn Slaven has a nice article about the WordPress scheduling technology.

Aside from WordPress and TypePad, I have confirmed this also works in Google Blogger. I’m not sure which other systems suport future-posting in this way.

Please let us know in the comments if you discover the feature works as expected on your blogging system of choice.

Coding For Readability

April 6th, 2007

Raymond Chen today reminds us that the readbility of code is important. But I’m not sure I agree with his headline/premise:

“Code is read much more often than it is written.”

In my opinion it’s more important for code to be skimmable than readable. This may be a lot of nitpicking over what is just supposed to be a catchy subject for Raymond’s blog, but I find it thought provoking. Let’s say you’ve got 100K of code. It’s OK if 90K of that code is completely unreadable, as long as it never needs to be modified again. That’s a big if, but my point is that the 10K that is actively developed can be well separated from the 90K of unreadable garbage, and you’re in good shape. Your code is skimmable.

In other words, don’t waste your time making already unreadable code “readable.” Just keep it in a dirty subroutine (and subfolder, probably!) where it belongs, and keep your high level code meaningful. I would guess that the vast majority of code in any shipping product has not been “read” in years. The products continue to evolve because they are skimmable. The change-prone portions have naturally eroded away from the giant clumps of unreadable junk.

Which isn’t to say that new code shouldn’t be as readable as possible. Interestingly enough, the article that prompted Raymond’s latest advice was an earlier one advising against BOOL parameters. He makes a good point, in recognizing that BOOL parameters in C or C++ do not often convey the parameter’s true meaning. Here is an area where Objective-C has a huge advantage with its inline-labeled parameters. Consider Raymond’s complaint:

“Even worse is that CreateEvent has two BOOL parameters. Like anybody reading the code later can remember which comes first.”

The Windows API he alludes to has a prototype like this:


HANDLE WINAPI
CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, 
				BOOL bManualReset,
				BOOL bInitialState,
				LPCTSTR lpName);

So you end up with a call that looks like this:


HANDLE myHandle = CreateEvent(myAttrs, TRUE, FALSE, "Ouch");

Indeed, Raymond was right. What do the TRUE and FALSE mean? The Objective-C equivalent of this CreateEvent method call would look more like:


HANDLE myHandle = [self createEventWithAttributes:myAttrs
				withManualResetting:YES
				signallingInitialState:NO
				eventName:@"Ahh..."];			

Damn it feels good to be a Cocoa programmer.

Update: It occurred to me shortly after writing this that when I do write C code, I often overcome this problem by /* inline-commenting */ the parameters. This technique was also described by somebody in the comments on Raymond’s blog.

Update 2: I didn’t think this post through too well before posting it, and now I feel like I’m suffering a bit of the fallout that comes from that. It’s easy to take from my post above that I have a nonchalant attitude about code readability. I meant it more as a riff on Raymond’s headline, and as an opportunity to add my belief that as important as readability is, skimmability is even more important.

Eric Albert wrote a thoughtful reply, to which I was motivated to also reply in his comments. I think my thoughts there might be also serve the permanent record of this entry here:

For the record, I am also in (nearly) complete agreement with Raymond. I mainly disagreed with his premise that code is read more often than it’s written. I don’t think that’s true.

And my opinions about this also come from being a code generalist. In particular, I think of the bugs I fixed in the Mac OS 7-9 days, when some of the ugliest, unreadable code imaginable was involved in the fixing. Often it was the skimmability of the outer layers that made it possible to pinpoint a bug, even if the final fix required cracking open some C file that was autotranslated from Pascal that was auto-translated from 68K Assembly.

In short: a giant code base is referenced much more like the yellow pages than like a novel. In the phone book, it’s nice when all of the entries are readable and well designed, but it’s much more important to be able ot skim to the section you’re most interested in right now.