The Cocoa-Carbon Advantage
September 7th, 2006I’ll let you in on a little secret. Well, it shouldn’t be a secret by now, but you’ll know I’m talking about you when I say that not everybody has gotten the memo yet. Don’t be embarrassed – today is the day you come into the light (not the “just died and moving on to a happier place” light, but close to it).
Cocoa is better than Carbon. And Carbon is better than Cocoa.
If you admit to me with a straight face that you know only one and refuse to venture into the other, I will immediately form the opinion that you are a bad programmer. A programmer I’d hate to be stuck in a MacGyver episode with. You couldn’t program your way out of a box. Or an NSRect. Or a RgnHandle. You sad, pathetic sack of unadaptable protoplasm. I loathe you. Actually, I love you. You make it easier for me to shine. If you don’t embrace and use every appropriate tool at your disposal on Mac OS X, well, you deserve to write crappy software! (And yes, in case anybody is wondering, I do think this means sometimes POSIX is better than Carbon, and Python is better than Cocoa, or Ruby is Cocoa — it all depends on what you’re trying to do).
The saddest thing in all of Macdom is the sight of Cocoa and Carbon purists crying in their mailing list beers because a given task is “impossible” in the API of their preference. Often a fearless API-hopper like Jim Correia or John Stiles will pop up and cheerfully announce a one-line solution to their woes. In the opposite API than the original poster had hoped, of course.
“Thanks for the response, but I’d like to keep this as pure as possible.”
Excuse me, I thought you wanted a solution. You idiot! What they really mean to say is “I learned this framework 10 years ago and I’ll be damned if I have to learn anything new now.” Yes, believe it or not, even Cocoa has idiots from 10 years ago who refuse to admit that there is value in Carbon. But by sheer force of numbers, the Carbon idiots are the sadder of the bunch.
Wake up people! It’s 2006. It doesn’t matter what you program in, it’s how you get the job done. Arguing about whether to use Carbon or Cocoa is like arguing about whether to use a net or a hook to catch a fish. You use whatever the circumstances call for. If you don’t, you die. (This, from the vegetarian, city-dwelling Mac programmer).
Why am I rambling on in this unusually caustic mood? Just a good excuse to get this off my chest and toss some code out that I’ve been meaning to share. It’s nothing special, but it will be good to seed google with it, and it is very well suited to the genre of code that can only be accomplished by a Carbon/Cocoa double-play.
Download NSImage+RSCarbonIcon (Free MIT License).
[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode([whateverTypeCode])]
Update 2: I confirmed my suspicion that the two approaches wouldn’t always return the same icon. Though in general the NSWorkspace call is quite reliable, consider the kColorSyncFolderIcon (‘prof’) type. Icon Services gets the expected image, while NSWorkspace apparently associates ‘prof’ with the profile file itself:
Note though, that the returned ColorSync folder is pixelated and old. It looks like Apple doesn’t use an icon on their ColorSync folder anymore. To my surprise, NSWorkspace is on the whole more reliable than GetIconRef, providing at least some icon at times when GetIconRef falls down. For instance:
Those are somewhat excusable because they’re sort of outdated. Neither icon is particularly correct, in any case. But the Icon Manager’s ultimate point of shame is that it fails while NSWorkspace succeeds in representing a sound file’s icon:
So NSWorkspace is, unless you are looking for an antique ColorSync folder icon, the preferable choice both for ease and functionality. Kind of takes the sizzle out of my example of where Cocoa should make use of Carbon, but it surprisingly demonstrates an example where Carbon clients would perhaps benefit by using NSWorkspace instead!
(Icon examples generated with the help of Paul Kim’s icon browsing test app)
This simple category on NSImage lets you easily produce an NSImage based on a Carbon “Icon Manager” type code. You’ll find a long list of these type codes in Icons.h, beneath the kSystemIconsCreator enumeration. Generic folder? No problem. Computer icon (inaccurate, but hey)? No problem. All of these NSImage at your disposal, which would otherwise “be impossible.”
It’s also useful in that it demonstrates how to properly make use of Carbon IconFamily data in a mixed-endian world. Thanks to a little documented caveat, these structures must always be treated as big-endian. So even if you figured out how to use the Carbon Icon Manager by yourself, maybe you’ll find it useful that this code sample ensures endian-safety across both PowerPC and Intel platforms.