When I was done with QA on Linguan 1.1.2 I wanted to submit it for review. But when I tried the validation step in Xcode halted me. It complained that I didn’t have a 512×512@2x icon. Then it dawned on me: Retina Macs.
So you have to imagine me, all excited about being able to submit this, but unable to do so. The icons for Linguan were all contained in an icns and I was stumped … but only for a moment. With help from David Smith I was able to prepare an iconset, the best current method for preparing the multiple resolutions of icons for Mac apps.
In previous Xcode versions developers would use the Icon Composer utility but Apple chose to remove that as of Xcode 4.4. Instead they recommend using icon sets in the official documentation. Icon Composer was deprecated because it was unable to deal with 1024*1024 resolution.
Icon sets consist of a folder containing all the required resolutions of the app icon. The name of the folder can be anything but – as unusual as it may seem – this folder has to have the .iconset extension. This is necessary to inform Xcode that it should create the icns file during the resource copying build phase.
The complete list of required sizes is this:
Since the 16×16@2x and the 32×32 are identical I was missing the 32×32 and 512×512 which I quickly got from my designer. I learned painfully that the iconutil tool seems to have problems with uppercase characters. At first I wanted to have my resulting icon to be named with an uppercase I, but strangely if you rename the above images accordingly then the tool will no longer be able to find any images. So I settled for all lowercase.
David Smith created the following shell script that creates all these files from the largest resolution. You need to have ImageMagick installed for the convert tool to work.
mkdir -p icon.iconset convert $1 -resize 16x16 icon.iconset/icon_16x16.png convert $1 -resize 32x32 email@example.com convert $1 -resize 32x32 icon.iconset/icon_32x32.png convert $1 -resize 64x64 firstname.lastname@example.org convert $1 -resize 128x128 icon.iconset/icon_128x128.png convert $1 -resize 256x256 email@example.com convert $1 -resize 256x256 icon.iconset/icon_256x256.png convert $1 -resize 512x512 firstname.lastname@example.org convert $1 -resize 512x512 icon.iconset/icon_512x512.png convert $1 -resize 1024x1024 email@example.com
Alternatively if you don’t want to install ImageMagick you can fall back on the sips tool which comes preinstalled on OS X.
mkdir -p icon.iconset sips --resampleWidth 16 $1 --out icon.iconset/icon_16x16.png sips --resampleWidth 32 $1 --out firstname.lastname@example.org sips --resampleWidth 32 $1 --out icon.iconset/icon_32x32.png sips --resampleWidth 64 $1 --out email@example.com sips --resampleWidth 128 $1 --out icon.iconset/icon_128x128.png sips --resampleWidth 256 $1 --out firstname.lastname@example.org sips --resampleWidth 256 $1 --out icon.iconset/icon_256x256.png sips --resampleWidth 512 $1 --out email@example.com sips --resampleWidth 512 $1 --out icon.iconset/icon_512x512.png sips --resampleWidth 1024 $1 --out firstname.lastname@example.org
Save the shell script in a text file named iconset.sh, chmod +x to make it executable and then call to produce the iconset folder:
When you drag and drop the iconset folder into Xcode you choose to copy it to the project. Instead of the normal yellow group folder icons you will see a blue folder which tells you that this is an actual folder on disk as opposed to a virtual group. When you select it you see a preview in the main editor view which you can resize between 16 and 512 points square with the slider at the bottom to preview the OS dynamically choosing the optimal base image for the given size.
If everything worked correctly you will see that Xcode is actually calling out to the iconutil tool for you and combine the icons. Check the build log to see it executing a ConvertIconSetFile set.
And indeed if you check the generated output product there is no longer any trace of the iconset folder. Instead there is an icon.icns file.
The build log kindly also tells us the exact script it executes. You can see that it uses the –convert icns option which means that the output should be an icns file. The other available option for this parameter is iconset to go the other way. With this you can start with an existing icon set and extra the individual pngs from it.
The CFBundleIconFile option in info.plist needs to match the file name of the resulting iconset. However you can omit the extension.
Icon sets are a handy addition to Mac apps that more or less replace the previous monolithic icns files. For a long time we’ve been used to working with multiple individual pngs on the iOS platform and this change of strategy also makes the Mac world be a little more like iOS.
If you have an existing project you can use the icon utility to split the icns file into the existing images and then add the missing resolutions before generating a new icon set.
Finally I am still astonished about iconutil being unable to work with input files that have an uppercase first character. So until this is fixed or somebody has a good explanation for me why this is, I’ll grungingly will name my Mac app icons with lowercase.