Wednesday, April 08, 2009

Extract UIKit artwork

While writing an iPhone application (more about it on this blog soon), I wanted to tint my UIAlertView with the same color I tinted my other controls. Maybe this is not a good idea, but I wanted to try anyway. Unfortunately, only UISearchBar, UISegmentedControl, UINavigationBar and UIToolbar have the tintColor property. So I started digging into UIKit. The first place to look was obviously the -(void)[UIAlertView(Private) drawRect:] method. To draw its background, a UIAlertView calls _popupAlertBackground which in turn call _UIImageWithName(@"UIPopupAlertSheetBackground.png"). This file probably lies inside the UIKit.framework would think a Mac developer. In fact it is not there. Only two pngs are there: DefaultWallpaper-iPhone.png and DefaultWallpaper-iPod.png. So, where is it?

It is in fact somehow embedded in the Other.artwork file which contains UIKit artwork. This file is memory mapped at application startup, probably for performance reasons and the content is easily accessed with the private _UIImageWithName() function. _UIImageWithName looks up in a dictionary that associates a file name to some memory location that contains the actual image data.

Now, it would be cool to extract all this content to see what artwork UIKit contains. It turns out to be quite easy. The only trick is to find a reference to the dictionary containing all the file names. Check my UIKit Artwork Extractor project on github to see how it works.

In an attempt to encourage comments, I'm offering a beer at NSConference to the first person who will clearly explain how to find the magic address of the images dictionary (except for Nicolas who knows the answer already) and I'm offering two beers to the one who provides a cleaner way to obtain a reference to the dictionary that is not UIKit version specific ;-)

Edit: I have updated the code so that it is not UIKit version specific, so I won the beers myself that I'm going to drink right away.