- Creating New Projects
- Building Hello World the Template Way
- Using the Simulator
- The Minimalist Hello World
- Converting Interface Builder Files to Their Objective-C Equivalents
- Using the Debugger
- Memory Management
- Recipe: Using Instruments to Detect Leaks
- Recipe: Using Instruments to Monitor Cached Object Allocations
- Analyzing Your Code
- Building for the iOS Device
- Detecting Simulator Builds with Compile-Time Checks
- Performing Runtime Compatibility Checks
- Pragma Marks
- Preparing for Distribution
- Over-the-Air Ad Hoc Distribution
- Submitting to the App Store
- Summary
Building for the iOS Device
Building for and testing in the simulator takes you only so far. The end goal of iOS development is to create applications that run on actual devices. There are three ways to do so: building for development, for App Store distribution, and for ad hoc deployment. These three, respectively, allow you to test locally on your device, to build for the App Store, and to build test and review versions of your applications that run on up to 100 registered devices. Chapter 1 introduced mobile provisions and showed how to create these in the Apple iOS Developer Program portal. Now it’s time to put these to use and deploy a program to the device itself.
Using a Development Provision
A development provision is a prerequisite for iOS deployment. Your team provisioning profile is automatically created and managed by Xcode. You can also create your own wildcard dev provision at Apple’s provisioning portal if desired, but it’s not really necessary anymore for basic development now that Xcode has introduced the team profile.
The Xcode Organizer (Command-Shift-2) provides the hub around which you can manage your provisions, certificates, and devices. Figure 3-16 shows the Organizer window with the Provisioning Profiles organizer displayed.
To enable automatic device provisioning, check the Automatic Device Provisioning box shown at the bottom of Figure 3-16. This option allows you to register new devices with Apple directly from the Organizer. Xcode automatically uploads device information to the developer portal and downloads an updated provision that adds the new device.
For the times you need to add provisions to Xcode directly, click the Import button at the bottom of the window. Navigate to the provision, select it, and click Open. The Provisioning Profiles organizer also allows you to view the provision creation and expiration dates.
The Developer Profile organizer lists all your iOS and Mac developer certificates for both development and distribution. The Import and Export buttons at the bottom of this organizer allow you to package up your developer identities for easy secure transfer to other computers. These certificates are stored in your system keychain. You may want to review your keychain and ensure that the WWDR (Worldwide Developer Relations) certificate is available for use. It is not listed in the Developer Profile organizer directly.
During compilation, Xcode matches the currently selected provision against your keychain identities. These must match or Xcode will be unable to finish compiling and signing your application. To check your certificates, open Keychain Access (from /Applications/Utilities) and type developer in the search box on the top right. You should see, at a minimum, your Apple Worldwide Developer Relations certifications authority and one labeled iPhone Developer followed by your (company) name.
Enable a Device
Tether a device that you wish to test on to your computer. You may need to wait for it to finish syncing in iTunes, first. For serious development, you can open Preferences in iTunes (Command-,), select the Devices tab, and check Prevent iPods, iPhones, and iPads from Syncing Automatically. Click OK to apply your new settings.
You can add devices to your account directly from Xcode. Select a device in the Xcode organizer (Window > Organizer, or Command-Shift-2). Right-click (or Control-click) its name and choose Add Device to Provisioning Portal (see Figure 3-17).
Figure 3-17. Use the Device organizer to add devices to the iOS provisioning portal.
Xcode will prompt you to log in to the iPhone provisioning portal with your program credentials. Once you’re authenticated, it will upload the device details and generate (or regenerate) your team provisioning profile.
First-time developers are sometimes scared that their device will be locked in some “development mode,” mostly due to Apple’s standard warning text; in reality, I have heard of no long-lasting issues. Regardless, do your homework before committing your device as a development unit. Read through the latest SDK release notes for details.
Inspect Your Application Identifier
Your project application identifier can be inspected and updated as needed. Select the project in the Project Navigator and choose TARGETS > Project Name. Select the Info tab to reveal the Custom iOS Target Properties, as shown in Figure 3-18. The application identifier can be set manually by editing the Bundle Identifier field. Xcode defaults to using your RFC 1034 reverse domain root identity followed by the product name.
Figure 3-18. The Info tab allows you to edit the Bundle identifier.
Your team development provision automatically matches all projects; its registered identifier is a single wildcard asterisk (*). Other provisions may or may not match the application identifier you are using. If you registered a wildcard application identifier of, say, com.sadun.* and used that to generate a provisioning profile, it would match com.sadun.helloworld or com.sadun.testing, for example, but not helloworld or com.mycompany.helloworld.
Set Your Device and Code Signing Identity
After checking your identifier, click PROJECT > project name > Build Settings. Enter device into the search field at the top-right of the Build Settings pane. This should match one setting: Targeted Device Family. Use this pop-up to select which devices you wish to compile for: iPhone, iPad, or iPhone/iPad. This last choice allows you to build a universal application that can install and run on both devices, taking advantage of each system’s native geometry.
Next, confirm your code-signing identity. Make sure you are looking at All settings (not just Basic ones). Enter signing in the top-right search field. Select your identity from the pop-up lists that appear to the right of each build type. As you start to accumulate provisions and identities, the list of options can become long, especially if you get involved in beta testing for third parties.
The two Automatic Profile Selectors automatically pick the first matching profile. I am paranoid enough to always inspect both the certificate name and the profile identity just above that name before choosing a profile. Apple recommends using automatic selection.
Set Your Base and Deployment SDK Targets
The Base SDK target setting specifies what version of the SDK is used to compile your application. Open PROJECT > project name > Build Settings and locate Base SDK at the top of the list. As a rule, you may keep this option set to Latest iOS. It will automatically match the most recently installed SDK. That means your code will not fail compilation if it uses the newest introduced APIs. The compiler will handle these correctly. However, your code may still fail at execution if new APIs are called on devices whose firmware does not yet support them—for example, calling a 5.1 API on a 4.3 device. That’s a problem you handle not with the Base SDK, but with the deployment target (see Figure 3-19).
Figure 3-19. The Base SDK sets the iOS version used to compile your applications. The armv7 architecture is currently available on the iPhone 3GS and newer, the iPod touch 3G and newer, and all iPads.
Set your deployment target in TARGET > project name > Summary > iOS Application Target in the first section of the Summary view. This pop-up (see Figure 3-20) specifies the earliest device that you wish to allow your application to install to.
Figure 3-20. Deployment Target sets the earliest iOS version that is permitted to run your application.
If you compile in 5.x and deploy to 4.x, you can use 5.x calls in your code but you will need to use runtime checks to ensure that you do not call APIs on platforms that do not support them and weak linking for any frameworks that aren’t found on the deployment target. Both runtime and compile-time code checks are covered later in this chapter. Setting the deployment target to the base SDK target ensures that you will never have to make any runtime API checks but limits your audience to only those customers who have updated their units to the latest firmware. The more you support earlier firmware releases, especially within the same iOS release family, such as 4.x, 5.x, and so forth, the more you increase your potential user base.
Compile and Run the Hello World Application
Finally, it’s time to test Hello World on an actual iPhone, iPod touch, or iPad. Before you compile, you must tell Xcode to build for the iOS device’s ARM architecture rather than the simulator’s Intel one. Locate the scheme pop-up at the top-left of your workspace’s toolbar and open it. It should look something like Figure 3-21. Device names appear at the top of the list, simulator choices at the bottom. Xcode highlights devices using firmware matching the deployment target but that are earlier than the Base SDK. Select a device.
Figure 3-21. Xcode makes a point of highlighting devices whose firmware lags behind the Base SDK. Older firmware installations form a vital component of your testing base to help ensure your code works on all valid deployment targets.
Choose Product > Run (Command-R) or click the Run button (it looks like a Play button) at the left of the workspace’s toolbar. Assuming you have followed the directions earlier in this chapter properly, the Hello World project should compile without error, copy over to the iPhone, and start running.
If the project warns you about the absence of an attached provisioned device, open the Xcode Organizer window and verify that the dot next to your device is green. If this is not the case, you may need to restart Xcode or reboot your device or your computer.
Signing Compiled Applications
You can sign already compiled applications at the command line using a simple shell script. This works for applications built for development. Signing applications directly helps developers share applications outside of ad hoc channels.
#! /bin/bash export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/ bin/codesign_allocate codesign -f -s "iPhone Developer" $1.app
If you use several iPhone Developer profiles in your keychain, you may need to adapt this script so that it matches only one of those; otherwise, codesign complains about ambiguous matching.
I personally use this approach to distribute test versions of the sample code from this book. Using developer code-signing skips the hassles of ad hoc distribution, allowing a rapid testing turn around without using up valuable device slots.