16
Jun
2008
 

Cocoa Tutorial: Custom Folder Icons

by Matt Long

This is just another one of those things that seems like it ought to be a simple little code snippet and you’re there, but in actuality it’s just not the case. I am building an exporter for my application that will export a movie project in iMovie HD format. I want to mimic the file format exactly and one of the things I noticed about the directories that are stored inside iMovie HD‘s custom format (select ‘Show Package Contents’ from the context menu in the Finder) is that they have custom icons assigned to them. So the problem to solve was how to do that programatically. Here is what I’ve found.

Stop The Presses After I published this yesterday, one of our kind readers pointed out in the comments that this problem has been solved much more elegantly using NSWorkspace starting in OS X Tiger (10.4). Yes. You read that right. Tiger! Heck if I could find this solution using Google, though. Oh well.. All you really need is - (BOOL)setIcon:(NSImage *)image forFile:(NSString *)fullPath options:(NSWorkspaceIconCreationOptions)options in NSWorkspace to do the same thing.

Feel free to read on as this will provide good legacy information. Just note that setting a custom icon for a folder is not as hard as this post would make it seem.

Poking A Stick At It

If you haven’t yet realized in your programming career that often the best and sometimes only way to figure something out is to ‘poke a stick at it’ then it’s probably time you started. I’m not sure where this reference comes from, but it seems apropo. Maybe it’s a cave man thing? You’re not sure what something is, so you poke a stick at it and see what happens.

Different from cave men, though, my proverbial/virtual stick is Terminal.app. If you look inside an iMovie HD project file, which contains folders with custom icons, using Terminal.app you’ll see a listing that looks something like this.

This is a list from a time lapse movie I made of myself making guacamole. You can watch it here if you’re so inclined. Notice that there are special attributes on each of the files and folders as indicated by the at (@) symbol. You can see what’s going on with a particular directory by using the mdls command. Try it on one of the folders, say Media for example. and you’ll get a listing like this.

Notice that the attribute called kMDItemFSHasCustomIcon is set to 1. If you now cd into the Media directory and run ls -al. You’ll see something like the following.

See that little 0 byte file called Icon?. This is what is telling the Finder about the custom icon being used.

The next step now that I knew that there was actually a way to specify a custom icon was to do a Google search to see if anyone had provided code to use. It was pretty sparse, but I was able to find something useful which is what this post is really about. A company called Shiny Frog based in Italy posted some open-source code that demonstrates how to set custom folder icons among other things. You can download their entire open-source code base here. I’ve leveraged only the folder icon setting code for this blog post.

Coding It Up

Here are the two projects for this post:
Set Custom Icon Project (Procedural Code)
Set Custom Icon Project (OO Code)

In the end, this post is not so much a tutorial as it is a showcase of the code. The code that it takes to change a folder icon is fairly lengthy. I have broken it out into two projects here. In the first, I broke out the code from the class that it was in when I downloaded it from Shiny Frog and put it into a procedural format. The second uses the classes as they’re found in the Shiny Frog code. Here is the code for the procedural way in its entirety. I’ve left all of the original comments from Shiny Frog in the code.

Note: If you want to simply use the code as classes, stick around for the next section in this post as I explain how you can just use what Shiny Frog provided.

Nearly 280 Lines of code later and here we are. I’m sure there is a group of people out there who don’t care about the internals of how this works and would like to just use the code. In fact I would wager that that’s probably the majority. Here’s all you need if that’s you. Just drop in the files NSString+CarbonFSRefCreation.m, NSString+CarbonFSRefCreation.h, IconFamily.m and IconFamily.h from the Shiny Frog project into your project and you can then change a folder icon with these few lines of code:

That’s a lot easier to read and use obviously. I recommend the object oriented approach as it keeps things much cleaner. And as Shiny Frog has released this code under a standard MIT license which allows you to do pretty much whatever you like as long as you maintain the copyright information, you could take the two classes here and create your own framework that you can then just link in whenever you need it.

Conclusion

When I searched for code online to figure out how to achieve setting a custom icon for folders it looked pretty slim. Had I needed to track down all of the steps myself it would have, obviously, taken much longer to figure out, but thanks the Shiny Frog, I was able to find the code to do exactly what I wanted. I’m hopeful that this blog post will hit the search engines and make it easier for folks to find as this seems like a fairly important thing to know how to do. Until next time.

Comments

enc says:

as i look at it, i think that 280 lines of code is a bit too much for this (even if we remove comments and whitespaces). i think there should be an easier way to code this up.

other than that – great piece of code. thanks!

Apple did finally take care of this mess in 10.4 by providing -[NSWorkspace setIcon:forFile:options:]. It lets you just pass in an NSImage you want to set for the icon and automagically takes care of the dirty work for you.

Matt Long says:

@Brian Webster

Hmmm. Now that’s handy. (… he says sheepishly). ;-)

Well this really draws into question my ability to track down a problem. Google!! You’ve failed me! :-D

Thanks for the pointer.

-Matt

The source of “poking things with a stick” was an Alan Kay interview. Alan Kay, for those who don’t know, was the inventor of Smalltalk and a luminary at Xerox PARC. He later was an Apple Fellow, and currently works on the Squeak project.

The context of Kay’s “poking things with a stick” is the design of the GUI interface we all are familiar with.

@Matt

This post is still very useful, just so we can show the damn kids these days how easy they have it.

“This is how we used to set a custom icon, with 300 lines of code! Uphill both ways through the snow! And that’s the way we liked it!”

:-)

girishkolari says:

I expected to have a badging icon to be displayed over a folder icon, when I tried it is displaying only the badging icon for the folder selected folder,

Basically I am trying to badge a file and folder in a particular location, is there any other solution then icon services?