Work Song

It’s not like I don’t have better things to do, but on the verge of sending a build to testers, and knowing I would probably forget to update the version number sooner or later, I set about putting a build date into my Xcode project. And for fun, I did it one better.

First off, the build date is pretty easy. Open up your project’s targets and right-click to do an “Add → New Build Phase → New Run Script Build Phase”. Under the Target, you’ll see a gray box called “Run Script”. Drag this to the top of the list of build phases – we want to do this step first – and do a Cmd-I to bring up its inspector. By default, scripts run with /bin/sh, which is fine. For the script body, just enter:

date > builddate.txt

Do a build and inspect your project’s directory to verify that the builddate.txt file got created. It’ll look like this:

Tue Nov 24 10:29:31 EST 2009

Assuming the file got created, drag the file to the “Resources” folder in your project. This will add a new item to the “Copy Bundle Resources” build phase, which is exactly what you want: the script will create the file, and then the copy phase will copy the file to your bundle. You probably don’t want to source control builddate.txt, since it’ll be created as part of the build (of course, if you don’t, anyone who checks out your project will see those files in red, since they’re missing, until they kick off a build).

Now it’s easy in code to get the contents of this file into your GUI or wherever else you need it (in my case, this code is in the “about” view controller’s viewDidLoad:):

buildDateLabel.text = [NSString stringWithFormat:@ "Built on %@", 
	[NSString stringWithContentsOfFile:
		[[NSBundle mainBundle] pathForResource:@"builddate" ofType:@"txt"]
	encoding: NSUTF8StringEncoding error:nil]];

Oh, but that’s not enough. I decided it was necessary to also let my testers know what tunes they should be listening to. So I added the following AppleScript file (inspired by Erik Rasmussen’s) to the project:

set track_name to ""
set track_artist to ""
tell application "iTunes"
		if not (exists current track) then return "(nothing playing)"
		set track_name to (get name of current track)
		set track_artist to (get artist of current track)
	end try
end tell
set build_tune to track_artist & " - " & track_name

The script’s return value is a string with the artist name and the song name, with a separator. If you call the script from the shell, it’s trivial to then dump the returned string into a file. So, create another Run Script Build Phase (you might want to rename these phases from the generic “Run Script”, BTW). This time, the script is:

/usr/bin/osascript iTunesTrackReader.scpt > itunestrack.txt

Again, drag this build phase before the Copy Bundle Resources phase. Once you’ve done a build, the itunestrack.txt file will exist, and you should copy it to the Resources folder, so it will get copied into your app bundle.

In the code, the “artist – song” string got a little wide on the phone, so I used a two-line label and replaced the separator with a new-line:

NSString *twoLineString = [[NSString stringWithContentsOfFile:
	[[NSBundle mainBundle] pathForResource:@"itunestrack" ofType:@"txt"]
	encoding: NSUTF8StringEncoding error:nil]
	stringByReplacingOccurrencesOfString: @" - " withString: @" -n"];
iTunesLabel.text = twoLineString;

And here’s the result (click for full-size):

Screen shot 2009-11-24 at 10.28.00 AM

OK, probably could have made better use of two hours, but it’s checked in now. Plus, it’s like an automated version-naming system: “are you running the “American Idiot” build or the “Kind of Blue” build?”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.