Categories
Uncategorized

Use sips and python to create vector-based AppIcon for iOS and OSX

I was surprised to see that Xcode does not make it easy to build all the various icon files for AppIcons for Mac OS and IOS. A few tools have been whipped together, but I’m not a fan of needing to install a whole new GUI app just to solve a simple problem. I’m also not a huge proponent of python, but it’s one of the scripting languages that natively supports JSON — which is part of how Apple’s implemented .xcassets (look inside you’ll see a file called Contents.json). So here is my solution — you’ll need to customize it for your own project. This particular project has two different AppIcon.appiconset entries in the xcassets file.

Note that this script re-writes the Contents.json file, to normalize the file naming. By default if you drag-and-drop files into Xcode it just adds -1 and -2 etc.. to the name, which is lame.

Whenever you update the icon (hardcoded here as a file called ‘icon.pdf’) re-run this script and the icon for you Mac and/or iOS app will update!

import re
import json
from subprocess import call
from pprint import pprint

for iconset in ['Design Show Server/Images.xcassets/AppIcon.appiconset', 'Design Show/Images.xcassets/AppIcon.appiconset']:
	json_data=open(iconset + '/Contents.json')
	newdata = []

	data = json.load(json_data)
	for img in data["images"]:
		size = int(re.sub(r'x.+$','', img["size"]))
		filename='{idiom:s}_{size:d}_{scale}.png'.format(idiom=img["idiom"],scale=img["scale"],size=size)
		filepath='{iconset:s}/{filename:s}'.format(iconset=iconset,filename=filename)
		if img["scale"] == '2x':
			size = size * 2
		newdata.append({ "filename" : filename, "size" : img["size"], "idiom" : img["idiom"], "scale" :img["scale"] })
		print('{filename:s} {size:d}'.format(filename=filename,size=size))
		call(['sips', '-s', 'format', 'png', '-Z', str(size), '-o', filepath, 'icon.pdf'])
	json_data.close()
	contents_file = open(iconset + '/Contents.json', "w")
	contents_file.write( json.dumps({ "images" : newdata, "info" : { "version" : 1, "author" : "andy's python script" }}) )
	contents_file.close()

Here’s a gist: