The 4 Most Useful Build Fixes for your new Apple Watch App

WatchKit 2 is the second iteration of the operating system behind Apple's most personalized product - the Apple Watch. It comes jam-packed with features like time travel and customizable watch faces. We have a great history of working with Apple. We have done two major releases of the Wealthsimple iPhone app, one of which was featured on the App Store, and loved the idea of including a watch app to show portfolios at a glance. We like to think of ourselves as a fast moving technology company - not just a financial institution - so we started on Swift from scratch and worked our way up on watchKit in under 2 weeks.

With the release of Xcode 7 for iOS 9 and watchOS 2, now is a great time to consider adding a watchKit app onto your existing iOS parent app. There are plenty of tutorials out there, but we still had to figure out a few things ourselves. Here are what we learned the hard way that we could not find online yet.

1. How to disable bitcode for your iOS app

What is bitcode in Xcode 7 and why do I care?

A new feature in Xcode 7 is App Thinning where you can define a more optimized app for each device Apple has created. This is done at the App Store level and requires you to provide the app in an intermediate-compatible format called bitcode. The App Store will then compile the bitcode down into the 64 or 32 bit executables for the thinned down versions as required.

The problem

While building your existing iOS app in Xcode 7, chances are you will come across a linker error relating to bitcode like this:

'<Some complicated path in your Pods>' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7  

Unfortunately, not all your Pods will be bitcode enabled and rebuilding a pod is not a sustainable practice.

The solution

To fix this problem, disable bitcode for your main iOS project.

  1. Select your iOS project as a target.
  2. Go to Build Settings > All > Build Options > Enable Bitcode
  3. Change it from Yes to No

This should allow you to build your iOS project with your existing Pods. You will, however, lose the new ability to thin your app.

2. How to match Version and Build numbers across the watch, watch extension, and parent app

The problem

When adding the watch app and watch extension, Xcode 7 by default will set each target's Version and Build numbers to the value of 1. However, the Version and Build number must be consistent across the parent app, the watch app, and the watch extension.

If they do not, you will get this error for mismatched Version numbers:

The value of CFBundleShortVersionString in your WatchKit app's Info.plist (1.0) does not match the value in your companion app's Info.plist (1.1.4). These values are required to match.  

Or you will get this error for the Build number:

The value of CFBundleVersion in your WatchKit app's Info.plist (1) does not match the value in your companion app's Info.plist (513). These values are required to match.  

The solution

To fix the Version number, set the Version number in both your watch app and watch extension to match the parent app.

For example in the Wealthsimple app: We changed the watch app and watch extension to have a Version number of 1.1.4, which matched our existing parent app.

To fix the Build number, you need to correct it in a similar way. Change the Build number in both your watch app and watch extension to be the same value as the parent app.

For example in the Wealthsimple app: We changed the watch app and watch extension to have a Build number of 513, which matched our existing parent app.

A more robust solution is to use build scripts in Xcode that will modify these values. As of this writing, Xcode 7 allows you add build scripts for the parent app and watch extension, but not the actual watch app. You may be able to programmatically fix this problem by having the same build scripts for each target when Xcode provides that functionality.

3. How to create provisioning profiles for your Apple Watch targets

The problem

When adding the watch app and watch extension, you create two new targets in your project. Your targets (the watch, watch extension, and parent app) will each have a unique value for Bundle Identifier.

You will need to create new provisioning profiles for each new target, in this case the watch app and watch extension. If you do not create new provisioning profiles, you will come across this error:

Code Sign error: Provisioning profile does not match bundle identifier: The provisioning profile specified in your build settings (“iOSTeam Provisioning Profile: com.wealthsimple”) has an AppID of “com.wealthsimple” which does not match your bundle identifier “com.wealthsimple.watchkitapp.watchkitextension”.  

The solution

To fix the code sign error, you will need to create new provisioning profiles for your new targets. This involves going into the Apple Developer website and adding new provisioning profiles.

  1. Go to the iOS App IDs section of Apple Developer
  2. Add a new app ID by clicking the + button.
  3. In App ID Description, give it a descriptive name. We called ours "Wealthsimple Watch app".
  4. For App ID Suffix, use Explicit App ID and fill in the Bundle ID field with what you have in Your project > Targets > WatchApp > Identity > Bundle Identifier
  5. Click Continue and Submit.
  6. Repeat this for your watch extension.
  7. Rebuilding should cause Xcode to create new provisioning profiles that match the new app IDs you have created and assign it to the correct targets.

For example in the Wealthsimple, we had to create two new iOS app IDs:
1. Wealthsimple Watch App with ID com.wealthsimple.watchkitapp
2. Wealthsimple Watch Extension with ID com.wealthsimple.watchkitapp.watchkitextension

4. How to fix a mismatched signing certificate

The problem

There are a number of different properties in the watch app and watch extension that must match the parent app. Another property that must match is the code signing identity. If they are not the same or not defined, you will get an error message like this:

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.

Embedded Binary Signing Certificate: nil  
Parent App Signing Certificate: iPhone Distribution: Wealthsimple (ABCDE12345)  

The solution

If the embedded binary signing certification is nil, then you are likely suffering from the incorrect provisioning profile that does not have any certificates attached to it. You will need to create a provisioning profile using the instructions above with the same signing certificate as the parent app.

If the embedded binary signing certification is not nil, you probably have one of these two problems:

  1. You have a provisioning profile that has the wrong certificate assigned to it. Check your assigned provisioning profile in Xcode and the certificates attached to it from the Apple Developer website. If you do not have a provisioning profile with the correct signing certificate, create a new provisioning profile by following the instructions above.
  2. You have set the wrong code signing identity to your target watch app and extension. Go to Targets > WatchApp or Extension > Build Settings > Code Signing > Code Signing Identity then change it to the correct parent app signing certificate.

Ship it!

We hope you found these tips helpful on your coding quest for your new Apple Watch app. If you want to take a look at what we ended up shipping (with new features like complications, time travel, and more), download it from the iTunes app store when iOS 9 and watchKit 2 go public, or sign up for Wealthsimple and start investing your money today!