Sharing iPhone projects

The latest version of Xcode has a “feature” that prevents you from specifying a wildcard name for the Code Signing Identity. (This feature does make it easier for new developers or people working alone, so I’m not going to write a Radar for this behavior.)

When you have multiple people working on an iPhone project, this behavior is very annoying because every developer has to change the Code Signing Identity before they can run the latest version on the device. Here’s a typical scenario:

  1. I set the Code Signing Identity to “iPhone Developer: Craig Hockenberry” and do my device build. Everything is wonderful and I check in a new SekretApp.xcodeproj/project.pbxproj.
  2. I add some cool new features to SekretApp and I want Anthony Piraino to try them out. Anthony updates his working copy to the latest version.
  3. Anthony has to change the Code Signing Identity to “iPhone Developer: Anthony Piraino” so that he can do the device build. He does, and everything is wonderful.
  4. Anthony then adds some new files to the project. He checks in a new SekretApp.xcodeproj/project.pbxproj as a result of this change.
  5. I need these new files, so I get the latest version of the project. Unfortunately, this latest version has Anthony’s Code Signing Identity in it. Everything is not wonderful.
  6. Lather, rinse, repeat.
It gets even more fun when you have merge conflicts. The solution to this problem is to get rid of the individual developer names in the project.pbxproj file.

Before you begin, make sure that you’ve closed the Xcode project you’re going to be updating. You are going to be modifying files used directly by Xcode, so things can get screwed up if you make changes while the project is alive.

The first step is to locate SekretApp.xcodeproj in the Finder and right click on the file. Select “Show Package Contents” to reveal the project.pbxproj file.

Now, open project.pbxproj with your favorite text editor and look for the Code Signing Identity. It will look something like this:

CODE_SIGN_IDENTITY = "iPhone Developer: Craig Hockenberry";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Craig Hockenberry";

Change the identity to look like this:

CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";

You also need to delete the embedded provisioning profiles. These are normally located a few lines below the CODE_SIGNING_IDENTITY:

PROVISIONING_PROFILE = "DEADBEEF-1337-FACE-F00D-EA7A7BADCAFE";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "DEADBEEF-1337-FACE-F00D-EA7A7BADCAFE";

(And, yes, I felt very lucky the day I was assigned that GUID.)

Note that there will probably be more than one CODE_SIGNING_IDENTITY (depending on your Project and Target settings.) Make sure to search through the whole file.

After making these changes, re-open the project in Xcode, clean it, and do a device build. If you make it through the CodeSign build phase, you’re good to go. Now all you have to do is check in the new version of project.pbxproj.

This trick works because the underlying codesign utility searches your keychain for a match. From the SIGNING IDENTITIES section of the manual page:

To be used for code signing, a digital identity must be stored in a key-chain that is on the calling user’s keychain search list. The identity is located by searching all such keychains for a certificate whose subject contains the identity string given. If there are multiple matches, the invocation fails and no signing is performed.

Since you and everyone else on your team has only one certificate with the pattern “iPhone Developer”, this search works correctly and no one will need to update the project settings after they check out the latest version of project.pbxproj.

And everything will stay fricken’ wonderful.