WatchKit App Code Signing with Xcode 6.3

Written by: on April 9, 2015

If you’re working on WatchKit extension for your iOS app, then you’re probably already familiar with the additional code signing trouble that can come along with it — additional bundle IDs, profiles, app groups, etc. You’ve probably also already spent some time getting it all working perfectly and hoped you wouldn’t have to touch it again any time soon. Then you updated to Xcode 6.3 and things broke. What changed?

During the binary validation phase of a build, you might be running into an error like this: "Embedded binary validation utility error: Error Domain=XCEmbeddedBinaryValidationUtilityErrorDomain Code=0 "error: Embedded binary is not signed with the same certificate as the parent app. Verify the embedded binary target's code sign settings match the parent app's." … followed by information about the certificates being used on the embedded binary and the parent app.

The problem here is that your WatchKit App and the parent app that it belongs to have been signed with different code signing identities after updating to Xcode 6.3. This validation step was occurring in Xcode 6.2, but build settings for the WatchKit App weren’t exposed in Xcode 6.2’s UI. Seemingly, the WatchKit app just inherited the build settings (including the code sign identity and provisioning profile) of the corresponding extension target. In Xcode 6.3, the WatchKit app target has its own build settings, and the newly-exposed build settings’ provisioning profile and code sign identity default to potentially problematic values (for us the provisioning profile went to Automatic, which changed the code sign identity to one that was unhelpful, resulting in a WatchKit app that was signed with a completely different identity than the parent app).

To fix the issue, you’ll need to go create a new provisioning profile that matches the bundle ID of your WatchKit app. Once you have a profile generated with the correct bundle ID and entitlements, add it to your provisioning profiles directory. Then, in Xcode, navigate to the Build Settings view for your WatchKit App target, find the Code Signing section, set PROVISIONING_PROFILE to the new one you just created, and make sure CODE_SIGN_IDENTITY has a value consistent with the parent app’s build settings.

Your problems may end here, but ours did not. We use Jenkins for continuous integration builds, and our Jenkins jobs include a pre-build script that sets the app’s bundle version to be the build number from Jenkins. After fixing our code signing issues, we ran into a new error: The value of CFBundleVersion in your WatchKit app's Info.plist (15) does not match the value in your companion app's Info.plist (1337). These values are required to match.

From this error message, we can see that our WatchKit app’s CFBundle Version is set to 15, while the parent app’s CFBundle Version is set to 1337. Previously, there was only ever one app whose version needed to be changed. With the WatchKit App, now we have a second app whose version number must match the parent app’s. You will now need to make sure that the CFBundleVersion in the Info.plist of your WatchKit App is identical to the CFBundleVersion in your parent app’s Info.plist, whether that’s controlled by a CI server or in your project file. While you’re at it, you may also want to go ahead and make the CFBundleVersion for any of your extensions match as well. Extension bundle version’s don’t currently have to match the parent, but who knows if or when that might change.

Full credit for identifying and resolving this issue goes to POSSIBLE Mobile iOS engineers Sean Coleman and Taylor Case.

Nick Arnott

Nick Arnott

Nick is the QA lead for POSSIBLE Mobile. In addition to Nick’s 9 years of professional QA experience, he brings a background of independent security research and proficiency in breaking things.

Add your voice to the discussion: