Joining the Party

You may have noticed something if you regularly read the weblogs that I read:

They

have

something

in common.

I’m a little late to the party, both getting there and telling the world about it, but I got my umbrella-topped pink drink (or membership card, depending on your metaphor) on June 21, a little over two weeks ago.

There will be things I can’t talk about, but considering the silence round these parts, it’s not like that’s going to cut off a vital flow of information you’ve come to depend on!

I’m hoping to be able to post more here, since, after all, it’s so well-named.

Wish me luck!

High Noon: The Shaming of MoreIsBetter

An image well, a Classic application, and a pair of utility libraries walk into a bar….

Hm, not bad – the punchline is left as an exercise for the reader – but I have in mind not so much humor as some sort of confrontation or showdown:

The Find_icon library keeps one hand poised above its holster and eyes its rival, the MoreIsBetter library, standing across the dusty town square….

Who wins at high noon?

Well, let’s back up a step: what are they fighting about? A demure image well stands to one side, hoping against hope that someone will bring it the file icon it so richly deserves.

Getting a file icon can be very easy indeed, nothing to fight over: GetIconRefFromFile() works from 8.5 on, including OS X.

But if you want to support earlier than 8.5 (and I do, for reasons I won’t go into right now), you need a way to get that file icon for every kind of file system object: a file, a folder, a file with a custom icon, etc. etc.

The first library I found that solves this problem is Find_icon, by James W. Walker, available from http://jwwalker.com/pages/find_icon.html. As with the best of these kinds of libraries, it has a rich history of support and fixes.

However, its contender, MoreIsBetter, available from http://developer.apple.com/samplecode/MoreIsBetter/MoreIsBetter.html, should have left it lying in the dirt after the first shot. Why? It has an even more illustrious history, is officially supported by Apple, and has been worked on by some of the sharpest developers there. But, for finding file icons, it can’t shoot straight.

For one, it doesn’t work properly in Panther. Now, this may be because I’m using a Classic application to talk to the OS X Finder (sending an Apple event to the Finder is the generally accepted way to get a file icon). Classic applications certainly aren’t Apple’s priority any more, but I think there’s a decent chance it won’t work from OS X apps either – I would bet it just hasn’t been officially tested under Panther.

For two, when I used it under earlier OSes, I found an egregious programming error – something I caught in my first try. Isn’t anyone else testing this thing? (I’ll send in a bug report, don’t worry.)

For three, even under older OSes, the icons it retrieves are garbage images. Unusable. But it reports no error. And I don’t have time to debug it right now.

I suspect no one’s testing this because MoreIsBetter is currently listed under “Legacy Technologies”. While MoreIsBetter does support older OSes (I was able to get it to compile for 68K), it does proudly support Carbon and OS X. In fact, it provides many functions that Carbon doesn’t and that would be painful to code yourself.

So why is it abandoned under “Legacy”? I don’t know, and it’s a shame. This gunslinger shouldn’t be retired just yet.

Addendum: I’ve been looking around for Carbon resources the same way I’m gathering Cocoa resources on the Web, and MoreIsBetter is a good example of why I can’t find them: the best examples are often labeled “legacy” or merely “Macintosh”, since they date back to a time when the Toolbox APIs that preceded Carbon were all there was of Macintosh APIs. So when I do finally present my Carbon links, don’t expect them to label themselves that way.

Golfing Another Round: More Cocoa Links

Here are more links to Cocoa Web sites or pages to add to the first batch I presented a couple months ago.

The full list now has permanent home, http://umbar.com/macdev/lists/cocoa.html, on this weblog’s companion site, Umbar.com.

Enjoy!

Cocoa Bindings simple tutorials from Apple:
http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings
I’ve seen developers talking on the mailing lists about issues when using Cocoa bindings for more complicated tasks, so don’t consider this the last word.

Harmless Cocoa, some apps, utility and UI classes, and a little font metrics tutorial:
http://harmless.de/cocoa.html

Welcome to HelpfulTiger!

Welcome to the Grand Opening of the HelpfulTiger weblog!

Why am I having a Grand Opening now, when I’ve already been posting for months?

For one, HelpfulTiger now has a new look! The new look is courtesy of Mark Abrams of look! designs, to whom I owe many thanks.

For two, I’m also officially re-introducing the Membrane library, something I’m very excited about.

For three, I’m introducing a new topic, “About a Blog”, where I’ll be discussing weblog news (like this).

And for four, I’m unveiling a new look, also courtesy of Mr. Abrams, for this weblog’s sister site, Umbar.com, where you’ll find Web pages devoted to some of the topics touched on in this weblog as well as my other projects. If you ever find yourself rummaging through the posts on this blog trying to find that download or list I mentioned, you should probably check out Umbar.com first.

And as always, enjoy!

Knowing Your Boundaries: C++/Objective-C with the Membrane Library

Apple’s preferred framework for writing new Mac OS X applications is Cocoa. Most cross-platform application development for the Mac not done by Apple is done in Carbon.

One reason for this state of affairs is that most large apps for the Mac are legacy apps, originally written for Mac OS 9 and earlier using the Toolbox. These large, flagship apps, such as Photoshop and Microsoft Office, are very important to the platform and with any luck won’t be going away anytime soon. For that reason alone, Apple must stick with a dual-API strategy.

But the second reason has to do with a different kind of history: the history of languages.

Apple’s OO language of choice is Objective-C, thanks to its NeXT heritage. Most cross-platform application development which isn’t done in scripting languages or Java is done in C++. Integrating large C++ and Objective-C codebases is just too hard. C++ and Objective-C code can be mixed, but their error-handling mechanisms and resource allocation traditions are incompatible, so there are no high-profile, large-scale examples.2 It’s easier to write (or buy, thank you, Metrowerks) your own C++ layer over Carbon, and stick with a single set of mechanisms.

Until now.

Well, more accurately, until June of 2003. That’s when Mac Murrett and I introduced the Membrane library to MacHack 18, along with a paper and sample code.

As the paper states in its introduction:

C++ and Objective-C can be used in the same codebase, but their error-handling mechanisms don’t mix well without some extra effort. This means careful resource allocation on both sides and translation code at every boundary between them. Sound like too much work? This paper describes the Membrane C++/Objective-C library, which makes these steps as easy as possible – often simple one-liners – while still both allowing for great flexibility and encouraging rigorous and systematic error-handling policies.

Membrane allows you to create rules for converting C++ exception types to Objective-C NSExceptions and vice versa. It allows you to encapsulate objects from one language in another so deallocation is automatic. This means you can develop the right way, fast.

For small codebases, this is not necessarily a big win. If you only call a few C++ APIs in your Cocoa application, you can just throw some try/catch blocks around them and be done with it. Alternately, if your C++ code doesn’t use exceptions much, you won’t need to convert them with Membrane.

So the conditions where Membrane will be really useful are: large codebase, modern C++ practices.

Working on such a project? Then go to the permanent Membrane Web page at http://umbar.com/membrane and have a look.


1Yes, there are exceptions, the biggest of them being iTunes. Funny coincidence that it’s the only new Apple app ported to Windows, eh?
2The exception to this statement being Safari and the C++ KDE codebase. But the KDE codebase is old and rarely uses such modern C++ best practices as exceptions.

0WNZ0RED

Don’t be alarmed.

Helpful Tiger has not been hacked.

No one’s going to take my home page and rewrite it so it’s filled with pictures of the Janet Jackson Maneuver from the Superbowl.

But I have been thinking about a certain kind of rewrite: code rewrites.

Joel Spolsky’s article on rewriting is clear: don’t throw away your old code and rewrite it from scratch, ever. No one appears to be arguing with him, and yet I’ve seen throw-away rewrite after rewrite, over and over again.

Why?

What’s in it for the developers?

One word: ownership.

When you rewrite code, it becomes yours. You’re invested in it, more focused on it, more willing to go the extra mile for bugfixes and enhancements.

This is the real benefit of rewrites. You may be able to convince a manager that the rewrite improved things, despite Spolsky’s arguments, because the rewrite improved you.

So how do you get those benefits without the downsides? Here are my thoughts, in no particular order, but phrased in the imperative, for both your and my consideration.

Enjoy!

Version 2 Syndrome
OK, so you’ve inherited a codebase. Most of the time, developers are already forced to work with such a codebase for a while before rewriting it. It’s only after the first new release is out the door, where they’re familiar enough with it to know its faults, but still not necessarily invested in it, that big rewrites get proposed. One idea for managers is to say: “Version 2 must still be based on the original codebase. You want to make changes? Propose them to me in terms of a series of changes to the existing codebase.” The challenge of implementing that may lead to more investment, more ownership.

Bye Bye Birdy
If you are going to allow a rewrite, don’t assign it to a developer who’ll be off the project in a few months. You’ve wasted your only concrete benefit! Same goes for “troubleshooters” brought in to fix a project on the ropes. Let ’em propose new designs, but let the developers who’ll be staying on the project do the work.

Square Peg
Some developers are just extraordinarily good at solving problems. They need to be challenged constantly, always chasing that Eureka! moment. And then the rest of the team is left with code that works, works really well, but nobody else understands. Such developers will never own anything. Trying to tie them to ownership is putting a square peg in a round hole. Put someone else in charge of that code, ASAP, so they can figure it out – and put questions about it to the original developer while she or he still remembers it. It’s an extra cost to involve a second developer, but it will be worth it.

Institutionalized
If a large, complicated codebase belongs to a company, but all the developers who worked on it have left or been abruptly transferred, it’s as if the company doesn’t really own it anymore. That may have been part of the problem with Netscape. The people who had owned the code weren’t in charge any more. Avoid this. Don’t move people around if the benefits – what, say, a certain developer can bring to a new project – don’t outweigh the costs – an eventual rewrite of another project’s codebase when major new functionality needs to be added.

This brings up the question: how do you transfer that real feeling of ownership? I don’t just mean formal responsibility, I mean the state of affairs where the new developers feel as invested in the code as the old ones did. The exact transfer process might be less important than finding the right kind of developer, willing to learn and commit to something external.

PDF Browser Plugin, SafariNoTimeout, Pacifist, and Iconographer (and Filthy Hypocrites)

Welcome to the newest Helpful Tiger category! Here’s where you’ll find out about the utilities I’ve found most useful in my programming endeavors.

PDF Browser Plugin
http://schubert-it.com/pluginpdf
In-browser viewer for PDF documents. Uses Apple’s PDF engine, so not a full-featured as Adobe’s viewer, but certainly very convenient, and it gets improvements when Apple’s engine improves. So, for instance, on 10.3 it can open Postscript documents.

I’ve found this plugin extremely useful for looking at documentation that I may not need permanently, but is only available in PDF format, such as the Unicode code charts.

Despite the fact that it’s free and Shubertit’s Web site also features shareware apps the poor man actually gets paid for, currently his Support page is mostly about PDF Browser Plugin and very informative.

He also has another free plugin for Microsoft Word.

And, err, some other stuff. Go look at that, too.

SafariNoTimeout
http://unsanity.com/haxies
A free Unsanity “haxie” that removes Safari’s 60-second connection timeout limit. Very helpful with Apple’s mailing list search pages, which I’ve talked about most recently in this post.

What!?, you’re saying to yourself. Didn’t I spend all that time telling you how to bypass Apple’s search pages? Don’t I “eat my own dog food”?

Okay, I admit it! I am a filthy hypocrite. I do use my own downloaded archives. Honestly. But– Apple’s site allows you to search for unrelated terms in a way unavailable to the client applications that I use to search the archives. If anybody is aware of an application that allows such OR-style searching, let me know. (And I’m not talking about grep, helpful as that can be.)

Also, if you’re on a new machine without the archives for a particular mailing list handy, it’s much easier to download this than wait 8 hours for all the archives to download, eh? It’s nice to have both techniques available when you need them.

Pacifist
http://charlessoft.com
A $20 shareware utility to open Mac OS X .pkg package files and allow you to extract individual files and folders out of them, as well as many other features.

This one’s a bit more special-purpose than the others, but I’ve found it helpful in the past when I’ve dealt more with OS X installer packages.

Iconographer
http://www.mscape.com/products/iconographer.html
A $15 shareware icon editor, especially useful for OS X-style icons.

I’ve found Icon Composer, the editor included with Apple’s developer tools, wanting in several respects, and Iconographer is in my opinion the best alternative for the money.

Cocoa Links, Part of a Good Breakfast

For a while now, I’ve been meaning to put together some good lists of links for Mac developers.

Here’s my first one, a list of Cocoa sites.

It’s based on a list from Paul Gobble of StudioBox, Inc. Thanks, Paul! I’ve edited the list and expanded it with my own contributions.

I’ll be adding to this in the future, as well as finding a permanent home for it. Feel free to suggest your own additions in the comments or, once they’re turned off, by emailing me. Enjoy!

Big Nerd Ranch, classes, books, and online resources, by Aaron Hillegass and others:
http://bignerdranch.com/

Blackhole Media BSD-Licensed Goodies:
http://blackholemedia.com/code/

Borkware LLC, some projects with source, MacEdition links, etc., by Mark Dalrymple and others:
http://borkware.com/

CamelBones, an Objective-C/Perl bridge framework, by Sherm Pendley:
http://camelbones.sourceforge.net/

Cocoa Dev Central, articles for “Cocoa newbies”:
http://cocoadevcentral.com/

CocoaDev, an OS X developer wiki (community-edited info site):
http://cocoadev.com/

The Cocoa Files, writings by Andrew Stone:
http://stone.com/The_Cocoa_Files/

Cocoa Literature List, by Jeff Biggus:
http://osx.hyperjeff.net/reference/CocoaArticles.php

Deep Cocoa, OpenGL tutorials by Katherine Tatters:
http://zerobyzero.ca/~ktatters/

Karelia Software‘s Cocoa Open Source:
http://cocoa.karelia.com/

MacDevCenter.com, articles, focus on Open Source, by O’Reilly:
http://macdevcenter.com/

Mamasam, a Resource Center for Cocoa Developers
Searchable archive of Apple’s cocoa-dev and OmniGroup’s MacOSX-dev mailing lists, and other resources.
http://cocoa.mamasam.com/

The Omni Group developer mailing lists:
http://omnigroup.com/developer/mailinglists/

Note the Omni Group does the Right Thing with its mailing lists and provides compressed archives for previous years’ messages. Apple? Hello? If you want such a feature yourself for Apple’s lists, see my rather high-bandwidth solution (original link and update).

Ranchero Software Weblog:
http://ranchero.com/

More Ranchero-provided Cocoa samples can be found at http://ranchero.com/cocoa/.

Unofficial cocoa-dev FAQ, by Alastair Houghton:
http://alastairs-place.net/cocoa/faq.txt

Double or Nothing: Pitfalls with NSTableView’s doubleAction

One of the core capabilities of Interface Builder, when used as the resource editor of a Cocoa application, is connecting UI widgets to code with just a bit of click and drag. The code that is connected to consists of outlets and actions.

Outlets are straightforward, just pointers to objects. The basic thing to remember, as with all Interface Builder connections, is that you shouldn’t try to refer to them in your init methods; use awakeFromNib instead.

Actions are methods, more specifically methods referred to by name (in the nib file) or selector (at runtime) instead of (as in C/C++) by pointer. To connect an action in Interface Builder, you control-drag from the UI widget that will send the action message to the object that will receive it, and then you choose the method in that receiver whose message will be sent.

The reason actions are more complicated than outlets is because actions are really part of a target/action pair. Interface Builder needs to remember more than just the message, it needs to remember the target to send that message to.

Until recently, to me at least, the Interface Builder UI seemed to be a little fuzzy on that distinction. In the Info window for an object, under the Connections pane, there was an Outlets column and an Actions column. Under the latest Interface Builder in Panther, what was called Actions is now referred to as “Target/Action”, which states the actual situation more explicitly.

Another thing to keep in mind is that the Cocoa framework has the action/target pair functionality built into Interface Builder solely for itself. You can’t make your own method/object pointer pair variables in a class and set them via the same Interface Builder UI that Cocoa uses for action/target; there’s just no way to tell Interface Builder to treat your variables that way.

With me so far? Good, because it’s about to get a little more complicated.


A while ago, I made a specialized outline view. When you double-clicked some of the cells, instead of getting the usual text editor, for certain columns and under certain circumstances, you would get more specialized behavior, such as a popup menu or a sheet with multi-line text editing capabilities.

The way to get this behavior is (a) turn off the regular editing behavior for the cell by having the delegate for the outline view return NO for the method outlineView:shouldEditTableColumn:item: and (b) send the message setDoubleAction: to the outline view with, as its parameter, the selector to the method you want to use to invoke the custom editor.

Those of you who know how this works already will protest, “Hey, you missed a step!” And indeed I did. But the above steps work under special circumstances, and they work because of how target/action pairs work.

The control-drag that I mentioned for actions at the top of this post fills in two variables in NSControl and its subclasses. It fills in the target variable with a pointer to the object. And it fills in the action variable with the selector to the method. Now, doubleAction is action‘s cousin in NSTableView. It works exactly the same way. But you can’t control-drag to connect it via Interface Builder, you need to set it via code. So, you would probably guess correctly that setDoubleAction: only sets the method, not the target, and you might look around in vain for setDoubleTarget:. Nope, doesn’t exist. Instead, it also uses target!

Why would this work even when you haven’t set target to anything? Well, if the target isn’t set, the Cocoa framework tries to make a guess what the target should be. You can see the order in which it checks here. This order doesn’t mention the delegate for a control, but NSTableView may be a special case since not all controls have delegates. In any case, it’s a good idea to send a setTarget: message explicitly.

There you have it. As with the solution to most pitfalls, esp. in Cocoa, the solution is very simple, but might not be easy to come up with on your own. Enjoy!

List Searching Update: Minor Bugfix and Xcode

I’ve uploaded a minor bugfix to my applelist.pl script, which I first announced on this Nov. 25, 2003 post. Line 154 has been changed from

system "./getlinks.pl $daypage $dayDir ".*.txt$"";

to

system "\"./getlinks.pl\" \"$daypage\" \"$dayDir\" \".*\.txt$\"";

Yes, ladies and gentlemen, I was bitten by the bug that often hits Unix scriptwriters getting used to the “Mac Way”: the annoying habit of real users to put spaces in their directory names. (Real users like me.)

In Unix scripting, spaces are often delimiters between arguments. If you have a script that takes two arguments, the first being a full path and the second being something else, and you pass in a full path not enclosed in quotes as that first argument, the script will parse everything after the first space it finds in that path as the second argument. Ugh.

When you’re working directly in Terminal, using things like tab completion or dragging in file/folders to get their paths, the OS handles this sort of thing for you by escaping out the spaces like this:

My\ HD/My\ Folder/

but you don’t want to do that sort of find and replace in your paths, and quotes are easier, anyway.
Second item of the day: people have been grumbling for a while now on the xcode-users list, which is the replacement list for projectbuilder-users in the same way that Xcode is the replacement for Project Builder (whose corresponding Apple Web site link now points to Xcode – is that a sign, or what?), that it does not yet have an entry in Apple’s list search page.

Now, there isn’t that much content in the list yet, just three months worth, but esp. considering that this is Xcode’s teething period, it’s nice to be able to search for specific problems you’re having or issues you’re facing. So I’m proud to say my applelist.pl script is the only way currently to enable such a search! Yes, yes, I know this state of affairs won’t last, but it’s nice to have bragging rights for a little while, eh?