RSpec-like Nested Contexts for XCTest

Posted by: on Jan 21, 2014 in Blog | Tags: , , | No Comments

There is a lot to like about the enhancements to the unit testing workflow in Xcode 5, in particular the ability to see in the gutter of a test suite which tests are passing and which are not, and to re-run a single test. Unfortunately, I am also a fan of Kiwi, Specta and their RSpec-like syntax, which doesn’t play well with the test navigator. One of the best ways to organize specs with those tools are nested contexts.

Read More

Xcode “Hard Mode”

Posted by: on Mar 29, 2013 in Blog | Tags: , , , , , | No Comments

In 2009, Peter Hosey wrote Warnings I turn on, and why. It remains an excellent explanation of why certain warnings, off by default, are a good idea to use. In it, he mentions the use of “treat warnings as errors” and calls it “hardass mode.”

Read More

Use a RAM Disk for DerivedData

Posted by: on Aug 15, 2012 in Blog | Tags: , , , , , | No Comments

Here’s a tip I picked up last night at our local Cocoaheads meeting: if you have a lot of RAM in your machine and a decent chunk of it is not currently in use, create a RAM disk and mount it at ~/Library/Developer/Xcode/DerivedData.

Read More

Unit Testing Cocoa with MacRuby

Posted by: on Sep 29, 2011 in Blog | Tags: , , , , , , | No Comments

I spend most of my development time split between Rails and iOS. Each offers a rich API that makes building projects much more productive and enjoyable. There is one place, however, that Ruby clobbers Objective-C: testing.

Read More

Your Own Private WWDC 2011

Posted by: on Jul 1, 2011 in Blog | Tags: , , , , | No Comments

Now that Apple has released the complete set of WWDC 2011 videos to registered developers, those of us who couldn’t make it to the conference have the opportunity to hear about all the new, shiny stuff coming in Mac OS X 10.7 and iOS 5.

Read More

Automatic Git Revision Stamping for App Store Projects

Posted by: on Nov 2, 2010 in Blog | Tags: , , , , , | No Comments

Following up on my post about automatic Subversion revision stamping, here is a modified script for use with Git-based projects.

Read More

Automatic Subversion Revision Stamping for iPhone Projects

Posted by: on May 26, 2010 in Blog | Tags: , , , , | 2 Comments

Early during development of a new iPhone OS application, I discovered that App Store submissions must use a strict format for the CFBundleVersion key in the Info.plist file. It can only be numbers and dots. This left me a little frustrated with how to version pre-1.0 releases to testers. I didn’t want to use an open-source style “0.9” and yet it wasn’t 1.0. What I really wanted was “1.0 b1” or similar.

I stumbled on Daniel Jalkut’s post about automatically stamping the Subversion revision into Info.plist and thought that might be a good way to go. I also created a new key in Info.plist, LYSApplicationDisplayVersion, that I use as a human-friendly version string, which is where I get my preferred “1.0 b1” form. CFBundleVersion now takes the form of major.minor.revision, where major and minor are the important parts of the human-friendly version (“1.0”) and revision is the Subversion revision number that produced the binary.

I like this method because it solves one problem raised by commenters on Daniel’s post. Because the Subversion revision is the third component, it doesn’t matter that r3999 is a mature 1.2 point release and r4000 is a risky pre-2.0 alpha for testers. Those versions end up 1.2.3999 and 2.0.4000 and it’s clear that they are from two different branches of development. For iPhone Ad Hoc distribution, iTunes also parses the version properly and knows that 1.0.100 is newer than 1.0.95.

Here is the script to paste into your custom script build phase:

# Xcode auto-versioning script for Subversion
# by Axel Andersson, modified by Daniel Jalkut to add
# "--revision HEAD" to the svn info line, which allows
# the latest revision to always be used.
 
use strict;
 
die "$0: Must be run from Xcode" unless $ENV{"BUILT_PRODUCTS_DIR"};
 
# Get the current subversion revision number and use it to set the CFBundleVersion value
my $REV = `/usr/bin/svnversion -n ./`;
my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Info.plist";
 
my $version = $REV;
 
# (Match the last group of digits and optional letter M/S/P):
 
# ugly yet functional (barely) regex by Daniel Jalkut:
#$version =~ s/([\d]*:)(\d+[M|S]*).*/$2/;
 
# better yet still functional regex via Kevin "Regex Nerd" Ballard
($version =~ m/(\d+)([MSP]*)$/) && ($version = $1);
 
die "$0: No Subversion revision found" unless $version;
die "$0: Modified, switched or partial working copy, you sure about that?" if $2 && ($ENV{"BUILD_STYLE"} eq "Ad Hoc" || $ENV{"BUILD_STYLE"} eq "App Store");
 
open(FH, "plutil -convert xml1 \"$INFO\" -o - |") or die "$0: $INFO: $!";
my $info = join("", <FH>);
close(FH);
 
$info =~ s/([\t ]+<key>CFBundleVersion<\/key>\n[\t ]+<string>\d+\.\d+).*?(<\/string>)/$1.$version$2/;
 
open(FH, "| plutil -convert binary1 - -o \"$INFO\"") or die "$0: $INFO: $!";
print FH $info;
close(FH);

There are a couple of other changes to this script for Subversion 1.5 and later, and for iPhone OS targets.

The first is that the regular expression allows for a trailing P in the Subversion revision. This signals a working copy from a sparse checkout, which I never use and therefore may be a problem. I have the script fail if any letter is appended to the revision when the BUILD_STYLE is “Ad Hoc” or “App Store”, which are two new configurations, cloned from Release, that I use for Ad Hoc and App Store distribution, respectively. Especially for modified working copies: I never want to accidentally hand out a build made from a modified working copy. Should the day come that I really do, I can comment this line out, make the build, and uncomment it again.

The second is that iPhone projects convert Info.plist to the binary plist format in the application bundle. In order to extract the existing CFBundleVersion key, it must be converted back to XML. When writing the plist back out, it is again converted to binary. Both of these steps use plutil, which is part of the Developer Tools.

Xcode User Defaults

Posted by: on Apr 29, 2010 in Blog | Tags: , | No Comments

Xcode as a development environment matches my working style fairly well, but there are two things about it that have bothered me. The first is a warning when I try to undo edits across a file save event. Since I have Xcode set up to save all files before a build, this happens often when I try an experiment and don’t like it.

The second is code completion for language constructs such as if statements. Xcode wants to do this:

if (condition) {
}

While I used this style a long time ago, today I want the opening brace on its own line:

if (condition)
{
}

No amount of digging in the preferences will provide a way to change these behaviors, however there is a lot of customizability hidden in the Xcode User Defaults. My two issues are solved quite easily:

$ defaults write com.apple.Xcode XCShowUndoPastSaveWarning NO
$ defaults write com.apple.Xcode XCCodeSenseFormattingOptions -dict BlockSeparator "\n"

malloc Debugging

Posted by: on Jan 12, 2010 in Blog | Tags: , | No Comments

Bill Bumgarner posted a nice tutorial on using malloc to debug memory misuse in Cocoa. I’ve run across these before when reading the malloc(1) man page, but it’s nice to have a tutorial that shows how to use them in practice.

Xcode: iPhone Project Dependency on Mac OS X Project

Posted by: on Oct 1, 2009 in Blog | Tags: | One Comment

This week, while building an iPhone application for a client, I wanted to run a custom Mac OS X command-line utility during the build phase of the iPhone project. I set up the command-line utility as a dependent project of the iPhone project, but it won’t build, telling me:

target specifies product type ‘com.apple.product-type.tool’, but there’s no such product type for the ‘iphonesimulator’ platform

There is no perfect solution to this problem, but here’s my workaround: rather than let Xcode build the dependent project for me, I simply added a call to xcodebuild as part of my custom script phase. As long as the input and output files for this phase are set up properly, the entire phase is skipped when the output file is up-to-date, and xcodebuild is pretty fast when the target binary is already built, too.

My final script phase looks like this:

(cd SubProject; xcodebuild -configuration Release)
SubProject/build/Release/SubProjectCommand