Click here to Skip to main content
Click here to Skip to main content

iOS 5 Developer's Cookbook: Building Your First Project

, 8 Dec 2011
Rate this:
Please Sign up or sign in to vote.
This is a chapter excerpt from iOS 5 Developer's Cookbook, The: Core Concepts and Essential Recipes for iOS Programmers, 3rd Edition

ShowCover.jpg

Erica Sadun
Published by Addison-Wesley Professional
ISBN-10: 0-321-75426-3
ISBN-13: 978-0-321-75426-4

Xcode helps you craft iOS SDK applications with an exciting suite of code editors and testing tools. This chapter introduces you to the basics of using Xcode to build your projects. You see how to build a simple Hello World project, compile and test it in the simulator, and then learn how to compile for and deploy to the device. You also discover some basic debugging tools and walk through their use as well as pick up some tips about handy compiler directives. This chapter also looks at how to submit to the App Store and perform ad hoc distribution for testing. By the time you finish this chapter, you’ll have followed the application-creation progress from start to finish and been shown valuable tricks along the way.

Creating New Projects

If diving into SDK programming without a lifeline seems daunting, be reassured. Xcode simplifies the process of getting started. It provides preconfigured projects that you can easily adapt while exploring the SDK. These projects provide fully working skeletons. All you need to do is add a little custom functionality to make that app your own.

To get started, launch Xcode 4 and choose File > New Project (Command-Shift-N). The New Project template window (see Figure 3-1) opens, allowing you to select one of these application styles to get started. These project styles are chosen to match the most common development patterns for iOS. Your choices are as follows:

Figure 3-1
The Xcode New Project template selection window. The Xcode interface will change as Apple continues evolving its design tools.
  • Document-Based Application—Intended for use with iCloud, the document template creates a starting point for building applications around ubiquitous elements.
  • Master-Detail Application—Usually based around lists and tables, master-detail applications let users drill their way through a hierarchical interface. These apps offer a tree-structured collection of interface choices, each choice sliding to a new screen or presenting, in the case of the iPad, in a separate detail view. The bars at the top of the navigation screens include an integrated Back button, letting users return to previous screens with a single tap. On the iPad, split views automatically accommodate themselves to match device orientations. In landscape mode, both views are shown at once; in portrait, the detail view is shown and the selection choices appear in via a navigation-bar-based popover.
  • OpenGL Game—When programming with OpenGL ES, all you need is a view to draw into and a timer that offers an animation heartbeat. The OpenGL Game template provides these elements, letting you build your OpenGL ES graphics on top.
  • Page-Based Application—Create a book-style application by choosing this page view controller-based template. New to iOS 5, the page view controller allows users to navigate through an electronic “book” using familiar touch-based gestures. The data source client feeds view controllers to the application, and a delegate allows the app to respond to gesture-based navigation and orientation updates.
  • Single View Application—This simple template provides a basic starting point for a primary view controller, offering storyboards for both iPhone and iPad distribution. Choose this style when you’re looking for an app that centers on a primary view rather than one that needs a specialized container style, such as a navigation controller, tab bar controller, split view controller, page view controller, and so on.
  • Tabbed Application—Apple’s iPod and YouTube applications offer typical examples of tab bar applications. In these applications, users can choose from a series of parallel screens by tapping buttons in a bar at the bottom of the application. For example, the YouTube application lets you choose from Featured Videos, Most Viewed, Bookmarks, and the search pane, each of which is accessed through a tab button. The Tabbed Application template provides a skeleton that you can grow to add panes and their contents. Although you can select either the iPhone or iPad as your target product in Xcode, Apple encourages you to avoid creating tab-bar-style applications on the iPad. The iPad’s generous screen space provides enough room that you do not need to fold your main interfaces using the conventions of tab bar and navigation applications.
  • Utility Application—Meant to be the simplest style of application, the Utility Application template creates a two-sided single-view presentation like the ones you see in the Stocks and Weather application. The template provides a main view and a flip view, which you can easily customize. This application template uses a simple flip-to-the-other-side presentation on the iPhone. On the iPad, it offers a popover linked to an information bar button item. Utility applications work best when they are highly focused. The flip-view or popover generally serves for in-app settings rather than an extension of the primary interface feature set.
  • Empty Application—The window-based application essentially offers the same template as the Single View one but without the storyboards. You get an application delegate and a customizable window, and that’s about it. One advantage of choosing this template is that it’s relatively easy to customize if you prefer to build your iPhone applications completely from scratch.

Note - Apple offers sample code and tutorials at the iOS Reference Library. Visit the library online at http://developer.apple.com/library/ios/navigation/index.html; you must use your developer credentials to access its contents. In addition to sample code, you’ll find release notes, technical notes, Getting Started guides, Coding How-To’s, and more. Many of these resources are also available directly in Xcode through its built-in documentation browser.

Building Hello World the Template Way

Xcode’s preconfigured templates offer the easiest path to creating a Hello World–style sample application. In the following steps, you create a new project, edit it to say “Hello World,” and run it on the iOS simulator. As you build your first Xcode project, you’ll discover some of the key development pathways.

Create a New Project

With the iOS SDK installed, launch Xcode. Close the Xcode Welcome page; it’s the window that says “Welcome to Xcode” and offers options such as Create a New Xcode Project. This window continues to appear until you uncheck “Show this window when Xcode launches” before closing it. Thereafter, you can access the page via Window > Welcome to Xcode (Command-Shift-1).

To create a new project, choose File > New > New Project (Command-Shift-N). This opens the template selection window shown in Figure 3-1. By default, the template selection window is embedded in a large new window, which is called a “workspace.” Workspaces embed all of Xcode’s editing and inspector features into a single window.

The left column in Figure 3-1 includes three iPhone project categories. These are Application (that is, the screen you see in Figure 3-1) Framework & Library (for creating static Cocoa Touch library modules), and Other (which initially contains a single, empty project style).

Choose Application > Single View Application and then click Next. Xcode opens a “Choose options for your new project:” screen, as shown in Figure 3-2. Enter Hello World for the project name and set the company identifier (for example, com.sadun). Company identifiers typically use reverse domain naming. The new application identifier appears below this in light grey text. In my case, this is com.sadun.Hello-World. Enter an optional class prefix. Xcode uses this to prepend template classes. If you enter ES, for example, Xcode creates ESAppDelegate.h and .m files. Choose Universal from the Device Family pop-up. Leave Use Storyboard checked. Leave Include Unit Tests unchecked. Click Next.

Figure 3-2
Once you set your company identifier, Xcode applies your settings between successive runs. This helps you avoid what was one of the most irritating features of previous Xcode releases—having to remember to edit your settings from “com.yourcompany” for each project.

Choose where to save the new project (such as the desktop) and click Save. A new Hello World Xcode workspace opens (see Figure 3-3). This project contains all the files needed to design a new, universal application centered on a single primary window. The files are grouped together into folders and listed in the left-hand pane, which is called the Navigator. Your new project is selected by default. Its project and target settings appear in the right-hand editor pane. This project settings editor is functionally similar to the target info pane found in earlier Xcode releases but with many improved features. The first editor pane you see allows you to choose orientation support and set application images.

Figure 3-3
This brand-new Hello World project was created by choosing one of the available templates. On older projects, you may see a “modernize” button on this screen as well.

Feel free to explore the files in your new project. Open groups (they look like folders but are just organizing aids for your project) to expose their contents, and then select any file to view it in the editor. To expose all the folders at once, Option-click the arrow next to the main project listing (that is, “Hello World” in this case) when no subfiles are showing. If files are showing, Option-click twice. The first click hides all the subfiles; the second click reveals them.

Xcode 4’s editor supports code, property lists, images (display only), and Interface Builder (IB) files. If you click, for example, on MainWindow_iPad.xib, you will open an IB editor pane. That’s a big change from Xcode 3, where Interface Builder was a separate program.

As Figure 3-3 shows, Xcode’s GUI has undergone massive changes from its 3.x incarnations. Whether you are new to iOS development or transitioning from an earlier SDK, it’s well worth exploring the Xcode workspace and its components. From a more integrated single-window workspace to the migration of Interface Builder into the main Xcode application, a lot of new features are waiting for you in Xcode 4.

Introducing the Xcode Workspace

Although it is not clear from Figure 3-3, the standard Xcode Project window is composed of three primary sections. You can best see this by clicking the Utility button at the top-right of the window. This is the second button from the right, and looks like a white rectangle with a smaller darker rectangle to its right. It is part of a set of seven buttons grouped as three buttons (labeled “Editor”), then three buttons (labeled “View”), then one button (labeled “Organizer”). Go ahead and click it to reveal the Utility section to the right of the editor. You may want to resize the workspace after exposing the Utility section.

Figure 3-4 shows the expanded workspace. It consists of three areas and a toolbar. From left to right, those areas include the Navigator pane, which allows you to browse project components, the Editor pane in the center, which provides editors and viewers for your files, and the Utility area to the right, which offers inspectors and library access.

Figure 3-4
The Xcode workspace consists of several areas, as shown here.

An optional debugging pane appears at the bottom of the editor when a program runs. You can show and hide it by clicking the debugger disclosure button at the bottom-left of the editor or by clicking the center of the three view buttons at the top-right corner of the Xcode window. The disclosure button is a small rectangle with an upward (“show”) or downward (“hide”) triangle. The view button is a rectangle with a darker embedded rectangle at its bottom.

A small central activity view appears in the center of the toolbar at the top of the window. It has a light blue color and can be found just under the window’s title. This view shows you the current state of your project and any ongoing activities, such as building code or an ongoing search. It looks a lot like the activity view you see in iTunes. Application run, stop, and breakpoint controls can be found just to the left of the activity view.

Controlling the Workspace

The seven buttons at the right of the workspace toolbar allow you to select the ways you want to view your workspace. Starting from the left, these buttons are as follows.

  • Editor buttons—These three editor buttons control how code is displayed in the central editor window. Your choices are standard, assistant, and version:
    • The standard editor (Command-Return) displays a single source code pane.
    • The assistant (Command-Option-Return) allows you to split your viewer in two, providing context-enhancing files in the secondary pane. The assistant can automatically find files and display file counterparts (for example, showing MyClass.h when viewing MyClass.m), superclass or subclass files, and so forth. The assistant is an absolutely brilliant feature of Xcode 4. Customize your assistant layout using the View > Assistant Layout submenu.
    • The version editor (Command-Shift-Option-Return) allows you to compare two versions of a single file against each other, so you can spot differences and see what has changed over time between separate commits.
    • View buttons—These three buttons allow you to hide and show the Navigator (left), Debug (center), and Utility (right) panes that appear in Figure 3-4. When all three are hidden, only the central editor pane appears. Doing so provides what appears to be a simple editor window but with quick access back to your project controls. You can also double-click files in the Navigator to open them up in new windows, with the other panes hidden.
    • Organizer button—Looking like a small window with smaller embedded rectangles, the Organizer button provides one-click access to the Xcode Organizer window. The Organizer, which is discussed later in this chapter, provides a single source for your mobile device controls, documentation, project organization, and more. You can also access the organizer by choosing Window > Organizer, or by pressing Command-Shift-2 on the keyboard.

    Note - Double-click any file listed in the Navigator to open it in a separate editor window. By default, this hides the top toolbar. Restore it by selecting View > Show Toolbar. There is no shortcut for this menu item by default, although you can add one using a third-party utility such as Quickeys or via the preferences’ key bindings pane.

    Xcode Navigators

    The left pane of the Xcode window doesn’t just list projects and folders. It handles a lot more as well. It’s called the “navigator area” and it lets you navigate information about projects in your workspace. Xcode 4 offers seven specialized navigators. Each navigator organizes information so you can browse through it. These navigators are accessed through the tab buttons at the top of the Navigator pane. Xcode 4 navigators include the following items:

    • The Project Navigator (Command-1) lists the groups and files that comprise your project. Selecting a file opens that file in an editor in the central pane. The kind of editor presented depends on the selected file. A code file (.h, .m, and so on) opens a code editor. Property list files, such as your Info.plist, open a property list editor. Interface files (.storyboard and .xib files) open in an Interface Builder (IB) editor, directly in the Xcode project window. This differs from earlier versions of Xcode, where IB was a standalone program, outside of Xcode.
    • The Symbol Navigator (Command-2) enumerates the classes, functions, and other symbols used within your project. Selecting a symbol opens the declaring header file, so you can instantly look up how the element is defined. The Utility > Symbols (Quick Help) inspector pane, found in the right-hand area on the other side of the editor, works synchronously with the Symbol Navigator by providing instant contextual documentation for any selected symbol, whether you select one from the Symbol Navigator or from the source editor.

    Note - When the Utility > Symbols (Quick Help) inspector is hidden, you can Option-click any symbol in the navigator or any text within a code editor to pop up an Xcode 4 Quick Help window with the same contextual documentation found in the Utility > Symbols pane. Use Option-double-click to open the item in the Organizer’s documentation window. Two buttons appear at the top-right of the Quick Help pop-up. The small book button leads to any existing documentation. The file icon with the “h” on it links to the declaring header file.

    • The Search Navigator (Command-3) provides an easy way to find text within your project. You can search both in your workspace (including any projects that have been added to the workspace) and in associated frameworks for instances of that text. Choose the search method you want to use from the text field pop-down as you type into the text field. A simple pop-up to the left of the search field lets you use find-and-replace features as well. You are not limited to searching via this Search Navigator. You can also search via Command-F (Edit > Find > ...) in any text-based editor.
    • Note - The small magnifying glass icon at the left of the search field in the Search Navigator plays an important role in controlling what documentation you search through. Click the magnifying glass and select Find Options to reveal options for matching your search phrase against source code.

    • The Issue Navigator (Command-4) provides a list of warnings and errors found during your build requests. Use this pane to select each issue and highlight its problem in the central code editor.
    • The Debug Navigator (Command-5) offers a way to examine threads and stacks during execution. When you select an item, the editor will instantly jump to either the source code or disassembly window, where you can see the current point of execution.
    • The Breakpoint Navigator (Command-6) provides a global list of debugging breakpoints within your project. Click any breakpoint to view it in-file in the editor.
    • The Log Navigator (Command-7) allows you to view your build results as a history. Click any past build to see the build log in the central editor pane.

    Xcode Utility Panes

    Context-specific helper panes appear in the right-hand utility pane. Like the left-hand navigator, the utility area can be shown or hidden as needed. This area consists of two sections: at the top is the Inspectors pane; at the bottom is the Libraries pane. Inspectors provide information about and options to customize a current selection. For example, when you select a label (a UILabel instance) in the embedded Interface Builder, you can set its alignment, background color, or dimensions using inspectors. Libraries offer pre-built components that you can incorporate into your project, and can include media and code snippets.

    Both panes provide a set of tabbed subpanes in a similar fashion to the Navigator panes. Buttons appear at the top of each pane. Inspector buttons update to match the context of the current selection. For example, the object attributes and connections inspectors that appear for a UILabel object do not appear when working with text in a source code editor. That’s because those Interface Builder–style inspectors have no meaning when working with source code. The Utility pane updates to match the currently selected item in the central editor.

    Inspector short cuts are Command-Option combined with a number, starting with 1 and 2 for the File (Command-Option-1) and Quick Help (Command-Option-2) inspectors, respectively. They increase numerically from there, depending on the available inspector utility panes. Typically IB-style inspectors include Identity (Command-Option-3), Attributes (Command-Option-4), Size (Command-Option-5), and Connections (Command-Option-6). Xcode 3.x users should note that the pane orders have been switched around a bit from what was used in 3.x Interface Builder, plus the old keyboard shortcuts no longer apply.

    Libraries use Command-Control-Option shortcuts combined with a number. The library pane provides access to file templates (Command-Control-Option-1), code snippets (Command-Control-Option-2), objects (Command-Control-Option-3), and media (Command-Control-Option-4). You can add your own custom elements into the code snippets libraries to provide easy access to repeated code patterns.

    Hide or reveal the Utilities section by typing Command-Control-Option-0.

    The Editor Window

    The editor window includes a primary space, where content is displayed. Above this space, you’ll find a “jump bar.” This bar simplifies finding other files using any level of grouping. Each of the path-like elements provides a pop-up menu, offering quick access to those elements. Jump bars appear in many Xcode 4 roles. They all work similarly and introduce a hierarchical way to move around a structured system.

    A special menu item, the small button with eight rectangles at the very left of the jump bar helps you find files related to the currently displayed item. Options include code counterparts (.m/.h file pairs), superclasses, subclasses, siblings, categories, included files, and more. This is a particularly powerful menu that you shouldn’t overlook.

    The central space of the editor window offers Quick Look technology to provide previews of nearly any kind of content you will add to your Xcode projects or will need to use in support of that project. This means you can use the content viewer not only for direct coding material, but also to review PDFs and keynote presentations that relate to developing the project, for example.

    Working with Multiple Editor Windows

    You may want to work with several editor windows at once. To accomplish this, you can create a new workspace window, work in one window using tabs, or detach a floating editor. Both windows and tabs allow you to switch quickly between various editors and files.

    To open new editor windows without taking an entire workspace with you, double-click any filename. A floating editor window appears above your workspace with the contents of that file.

    To create a new workspace window, choose File > New > New Window (Command-Shift-T). The new window contains the same project or projects as the original workspace. Changes to a file in one window or tab are mirrored to the same file in other windows or tabs.

    Note - To add line numbers to your source code editing windows, open Preferences (Xcode > Preferences, Command-,). Select the Text Editing pane and check Line Numbers.

    To use tabs, choose View > Show Tab Bar. This reveals a workspace tab bar between the main toolbar and the panes below it. Create new tabs using File > New Tab (Command-T) or right-click (Control-click) in the tab bar and choose New Tab from the contextual pop-up. Alternatively, press Shift-Option while clicking a filename in the navigator and click the + button at the top-right to open the file in a new tab.

    Xcode tabs follow Apple’s standards, so if you’re used to using Safari tabs, they’ll work similarly in Xcode. To navigate between tabs from the keyboard use Command-Shift-[ to move left and Command-Shift-] to move right. Click + to add a new tab to your window. You can pull tabs out into their own windows and can drop tabs into existing windows by adding them to tab bars.

    The Cocoa Samurai blog (cocoasamurai.blogspot.com) created a number of Xcode 4 keyboard shortcut reference guides. These infographics, which are hosted at github (github.com/Machx/Xcode-Keyboard-Shortcuts), provide an exhaustive guide to the key combinations you can use to navigate through Xcode.

    Note - Xcode provides full Undo support for a single session. You can even undo past a previous save so long as you do so within the same session. That is, you cannot close a project, reopen it, and then revert changes made before the project was closed.

    Review the Project

    When Xcode creates your new project, it populates it with all the basic elements and frameworks you need to build your first iOS application. Items you see in this project include the following:

    • Frameworks > Foundation and Core Graphics frameworks—These essential frameworks enable you to build your iPhone applications and are similar to the ones found on OS X.
    • Frameworks > UIKit framework—This framework provides iOS-specific user interface APIs and is key to developing applications that can be seen and interacted with on the iPhone screen.
    • Products > HelloWorld.app—This placeholder is used to store your finished application. Like on the Macintosh, iPhone applications are bundles and consist of many items stored in a central folder.
    • Supporting Files > HelloWorld-Info.plist—This file describes your application to the iPhone’s system and enables you to specify its executable, its application identifier, and other key features. It works in the same way Info.plist files work on the Mac. Localizable strings for the property list can be found in the Supporting Files > InfoPlist.strings file(s).
    • MainStoryboard_iPhone.storyboard and MainStoryboard_iPad.storyboard—These Interface Builder files create a minimally populated GUI for each platform. You will modify the upcoming walkthrough.
    • [Prefix]AppDelegate.h, [Prefix]AppDelegate.m, [Prefix]ViewController.h, [Prefix]ViewController.m, main.m—These files contain a rough Objective-C skeleton that you can customize and expand to create your application. The prefix used by these files is set in the new project options screen. Feel free to browse through the code, but you will not edit these files in the upcoming walkthrough. Instead, you use the way that Xcode set them up and limit your modifications to the Interface Builder storyboards.

    Note - To add frameworks to your project in Xcode 4, select your blue project file in the Project Navigator. In the central editor pane, click TARGETS > Target Name in the very left column. Click Build Phases and open the Link Binary With Libraries disclosure triangle. Click the + button, navigate to the framework you wish to add (you’ll find standard frameworks under Device folders), select it, and click Add. An options pane opens. Uncheck Copy items into destination group’s folder (if needed), make sure that your target remains checked, and click Finish. To remove a framework, simply select it and click -.

    Open the iPhone Storyboard

    Locate the MainStoryboard_iPhone.storyboard file in the Project Navigator. Storyboards store Interface Builder layouts and can include all the screens (called “scenes”) for a single application. Select the storyboard file to open it in the central editor so you can begin to edit the file. You will see a grid pattern in the background of the editor and a scene list on the left side of the window. This list initially consists of the single Hello World View Controller Scene. The scene appears in the gridded area and consists of an empty view on top and an associated object dock beneath it. Figure 3-5 shows how this looks.

    Figure 3-5
    The Interface Builder window for an iPhone storyboard. A small dock floats below each storyboard scene, offering access to objects associated with its view.

    The two icons in the dock represent elements of the interface you’re editing. On the right is the view’s owner—in this case, its view controller. It represents the view controllers attached to the view.

    View controllers don’t have a visual presentation. They manage views, but they don’t display anything of their own. Each view controller has a property called “view” that is set to some UIView responsible for providing the actual onscreen presentation. Here, that view is displayed above the dock. You can see more about the controller by selecting it and opening View > Utilities > Show Identity Inspector. Observe the class listed in the inspector (ESViewController or similar).

    The view controller element in the dock is called a “proxy.” A proxy plays a role in IB but the object that it represents (the view controller) is not itself embedded in the .storyboard archive. This proxy represents the object that loads and owns the view.

    To see how items are connected to each other, choose View > Utilities > Show Connections Inspector. You see an outlet listed called “view.” Hover your mouse over this outlet and the view darkens. A small tooltip (saying “View”) appears as well. That’s because the view outlet for your view controller is already connected to that view. Outlet is IB-talk for “instance variable.”

    The other icon, the one that appears in the left position of the dock, is called First Responder. It looks like a dark orange cube with the number 1 on it. Like the view controller, it’s a proxy object. It represents the onscreen object that is currently responding to user touches. During the lifetime of an application, the first responder changes as users interact with the screen. For example, imagine a form. As the user touches each text field in that form, that field becomes active and assumes the first responder role. At times you want to allow interface elements (such as buttons and switches) to control whatever item is the first responder. Connecting to this proxy in Interface Builder allows you to do so.

    Edit the View

    To start customizing, click the big white view. By default, this view is empty although it shows a status bar at the top. It’s up to you to customize this and add any content. To do so, you rely on two tools from the Utility area: the Interface Builder object library and the inspector.

    Choose View > Utilities > Show Attributes Inspector (Command-Option-4). The Attributes Inspector lets you adjust the properties of the currently selected object—in this case, the view that you are editing. In the inspector, locate the View > Background Listing with its colored swatch. Click the swatch and choose a new color from the Colors palette. The view you are editing automatically updates its background color.

    Next, open the object library by choosing the third icon at the top of the bottom pane. Alternatively, select View > Utilities > Show Object Library (Command-Control-Option-3). This library (see Figure 3-6) presents a list of prebuilt Cocoa Touch elements you can use in your IB files. These include both abstract elements such as view controllers as well as visual components such as buttons and sliders. Enter label in the search field at the bottom of the library. Drag the label from the middle pane and drop it onto your window. (Alternatively, double-click the label in the library. This automatically adds that item to your window.)

    Figure 3-6
    The Interface Builder object library.

    Once it is dragged to the view, double-click the label and change the words from “Label” to “Hello World.” You can also move the label around in the window to appeal to your aesthetic sensibilities or set its location in the Size Inspector. The Attributes Inspector allows you to set the font face and size, as well as the text color. You may need to resize your label to accommodate the new size. Unselect “Autoshrink” and note that there are two places to set the font size. The field in the main inspector sets the minimum font size for the label. The pop-up for the font sets the desired font size.

    Save your project with File > Save (Command-S). You have now customized your iPhone window with this content.

    Next, customize the iPad interface. Return to the Project Navigator and select MainStoryboard_iPad.storyboard. You’ll notice that the iPad presentation is far larger than the iPhone one. You may not be able to see the entire iPad interface at once, even on relatively large screens.

    Interface Builder allows you to double-click in the grid background to shrink the presentation to a more manageable size, but you cannot perform edits in this mode. You can also use the new zoom/shrink buttons at the bottom-right of the editor window. Many developers find it worth investing in a large vertical monitor rather than a horizontal one in order to better work with iPad edits in IB.

    As before, change the view’s background color, add a label (“Hello World on iPad,” perhaps) and mess with its font and placement. Again, save your project (File > Save, Command-S).

    Run Your Application

    Locate the pop-up in the workspace toolbar just to the right of the Start/Stop buttons at the top-left of the window. From this pop-up choose Hello World > iPhone Simulator. This tells Xcode to compile your project for the Macintosh-based iPhone simulator. If more than one simulator choice presents, select the most recent SDK (that is, 5.3 rather than 5.0).

    Click the run button (by default it looks like a “Play” button) or type Command-R and then wait as Xcode gets to work. It takes a few seconds to finish compiling, and then Xcode automatically launches the simulator, installs your project, and runs it. Figure 3-7 shows the result, the Hello World application running on the simulator.

    Figure 3-7
    The customized Hello World application runs on the simulator.

    After testing the application on the iPhone simulator, click the stop button (to the right of the run button) and test the application using the iPad simulator. Select Hello World > iPad Simulator from the pop-up and again click the run button.

    Using the Simulator

    The iOS SDK simulator makes it possible to test applications on the Macintosh using many of the same actions a user would perform on an actual device. Because the Macintosh is not a handheld touch-based mobile system, you must use menus, keyboard shortcuts, and the mouse or trackpad to approximate iPhone-style interactions. Table 3-1 shows how to perform these tasks via the simulator.

    Table 3-1  Simulator Equivalents for iPhone Actions

    Action Simulator Equivalent
    Selecting the device Use Hardware > Device to simulate an original iPhone, Retina iPhone, or iPad-style device. Firmware versions are selectable via Hardware > Version.
    Rotating the device Hardware > Rotate Left (Command-left arrow) and Hardware > Rotate Right (Command-right arrow). The simulator supports all four major interface orientations: portrait, landscape left, landscape right, and portrait upside down. You cannot simulate face-up or face-down orientations.
    Shaking the device Hardware > Shake Gesture (Command-Control-Z). This simulates a shake using a motion event but does not simulate other accelerometer actions. I encourage you to avoid building applications that depend on users shaking devices, no matter how cool the feature appears.
    Pressing the Home key Click the Home button on the simulator screen or choose Hardware > Home (Command-Shift-H).
    Locking the device Hardware > Lock (Command-L).
    Tapping and double-tapping Click with the mouse, either a single- or double-click.
    Tapping on the keyboard Click the virtual keyboard or type on the Mac keyboard. You can use many Mac-style shortcuts for ease of testing, including Command-A, Command-C, and so on.
    Dragging, swiping, and flicking Click, drag, and release with the mouse. The speed of the drag determines the action. For flicks, drag very quickly.
    Pinching in or out Press and hold the Option key on your keyboard. When the two dots appear, drag them toward each other or away from each other. Hold down the Shift key to move the dot’s origin point.
    Running out of memory Hardware > Simulate Memory Warning. This allows you to simulate a condition of low available memory, letting you test how your application responds.
    In-progress phone call (visual display only) Hardware > Toggle In-Call Status Bar. On the iPhone, you can run an application while on a phone call. The in-call bar appears at the top of the screen for the duration of the call.
    Attaching a keyboard Simulate the detection of a Bluetooth or docked hardware keyboard by selecting Hardware > Simulate Hardware Keyboard.
    Attaching TV Out cables Choose Hardware > TV Out to simulate the attachment of a VGA or HDMI cable to the dock connector. Use this to test your external screen code, and specifically to catch screen-attached and -detached notifications. A floating window shows the simulated output.
    Changing zoom Change the magnification of the simulator by selecting Window > Scale. Choose from 100%, 75%, and 50%.
    Simulating a printer Choose File > Open Printer Simulator to test your software with AirPrint. You can also use this simulator to test printing from a device. The printed output opens in Preview.
    Capturing screenshots Choose File > Save Screen Shot (Command-S) or copy the screen with Edit > Copy Screen (Command-Control-C).
    Setting a simulated location Use the Debug > Location menu to simulate where the iPhone is being used. Choose from a (stationary) custom location, Apple’s HQ, Apple Stores, a city bike ride/run, or a drive down the freeway.
    Slowing down animations Choose Debug > Toggle Slow Animations to allow you to better view animations over a longer period of time. Use this feature to spot inconsistencies and flaws in your animations.
    Highlighting potential rendering trouble spots Use the four Debug > Color options to locate potential presentation issues. The items, which are toggled on and off via menu selection, include blended layers, copied images, misaligned images, and elements rendered off-screen.
    Resetting the simulator Choose iOS Simulator > Reset Contents and Settings to restore your simulator to its “factory fresh” original condition, deleting all current applications, settings, and user data.

    Simulator: Behind the Scenes

    Because the simulator runs on a Macintosh, Xcode compiles simulated applications for the Intel chip. Your application basically runs natively on the Macintosh within the simulator using a set of Intel-based frameworks that mirror the frameworks installed with iOS onto actual units. The simulator versions of these frameworks are typically located in the Xcode developer directory, in /Developer/Platforms/iPhoneSimulator.platform/Developer/ SDKs/iPhoneSimulator5.0.sdk/System/Library or some similar location. The actual location will vary by the version of the SDK you are using and where you have installed the SDK. The /Developer folder is the default location, but you can easily override this.

    You can find your applications in your home’s Library/Application Support folder. They are stored in iPhone Simulator/ in one of many firmware-specific folders, such as 3.1.2/, 4.2/, and 6.1/ under User/Applications/. It’s helpful to visit these folders to peek under the hood and see how applications get deployed to the iPhone; these User/ Applications/ folders mimic device installations. Other interesting development folders include the following:

    • /Developer/Platforms/iPhoneSimulator.platform/Developer/ Applications—Default location of the actual iPhone simulator application.
    • /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/ iPhoneSimulatorX.X.sdk/Applications—Location of the simulator’s built-in applications, including Mobile Safari, the Address Book, and so forth. Replace X.X with the firmware version.
    • /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/ iPhoneSimulator5.0.sdk/System/Library/Frameworks—Location of the Cocoa Touch frameworks you can link to from your application.
    • /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/ Templates/Project Templates/Application—Location of the individual project templates shown in Figure 3-1.
    • ~/Library/MobileDevice/Provisioning Profiles—Folder that stores your iPhone Portal provisioning profiles.
    • ~/Library/Developer/Xcode/Archives—Folder that stores archives built with the Build > Build and Archive option in Xcode. Archived applications appear in your Xcode Organizer, where they can be validated, shared, and submitted to iTunes Connect.
    • ~/Library/Developer/Xcode/DerivedData—Build and log folder.
    • ~/Library/Developer/Xcode/Snapshots—Project version control snapshots.
    • ~/Library/Developer/Shared/Xcode/Screenshots/—Folder for screenshots taken with the Organizer.
    • ~/Library/Developer/Shared/Project Templates/—Add custom templates to this folder to have them appear in the New Project screen.
    • ~/Library/MobileDevice/Software Images—Folder that stores iOS firmware files (.ipsw files) that can be installed onto your devices.
    • ~/Library/Application Support/MobileSync/Backup—Folder where iTunes stores iPhone, iPod touch, and iPad backup files.

    Note - Application archives let you share applications as .ipa files. They also allow you to run the same validation tests that iTunes Connect uses to confirm that an application is properly signed with a development certificate before or as you submit your apps.

    Each application is stored in an individual sandbox. The name of the sandbox is random, using a unique code (generated by CFUUIDCreateString()). You can zip up a sandbox folder and be able to share it between Macintoshes. The other Macintosh will need Xcode to be installed in able to access the simulator and its frameworks.

    Each sandbox name hides the application it’s hosting, so you must peek inside to see what’s there. Inside you find the application bundle (HelloWorld.app, for example), a Documents folder, a Library folder, and a temporary (/tmp) folder. While running, each application is limited to accessing these local folders. They cannot use the main user library as applications might on a Macintosh.

    With the exception of the Library/Caches folder, all the materials in an application’s Documents and Library folders are backed up by iTunes when deployed to a device. The tmp folder is not backed up by iTunes. Use the Caches folder to store large, changing application-support data files that need to persist. Use the tmp folder for materials that iOS can dispose of between application launches.

    If you want to clean out your applications’ sandbox folders, you can delete files directly while the simulator is not running. You can also delete all the simulator data by choosing iPhone Simulator > Reset Contents and Settings from the simulator itself. This erases applications, their sandboxes, and any current settings, such as nondefault language choices, that affect how your simulator runs.

    Alternatively, use the press-and-hold-until-it-jiggles interface on the simulator that you’re used to on the iPhone device itself. After you press and hold any icon for a few seconds, the application icons start to jiggle. Once in this edit mode, you can move icons around or press the corner X icon to delete applications along with their data. Press the Home button to exit edit mode.

    Although applications cannot access the user library folder, you can. If you want to edit the simulator’s library, the files are stored in the iPhone Simulator/User/Library folder in your home Application Support folder. Editing your library lets you test applications that depend on the address book, for example. You can load different address book sqlitedb files into Library/AddressBook to test your source with just a few or many contacts.

    Note - The iPhone simulator and Mac OS X use separate clipboards. The simulator stores its own clipboard data, which it gathers from iOS copy/paste calls. When you use Edit > Paste (Command-V), the simulator pastes text from the Macintosh clipboard into the simulator’s clipboard. You can then use the simulator’s Edit menu (double-tap in a text box) to paste from the iOS clipboard into simulator applications.

    Sharing Simulator Applications

    Simulator-compiled applications provide an important way to share test builds when developers are denied access to new hardware or when beta firmware is not widely distributed. They can also support interface design testing in advance of actual device deployment. Although unsuitable for full debugging and end-user usability tests (see Chapter 1, “Introducing the iOS SDK”), simulator builds do have a role and a purpose in iOS application life cycle.

    To share an app, zip up its entire sandbox folder from one Macintosh and then extract it to another Mac’s simulator application folder.

    The Minimalist Hello World

    While exploring the iOS SDK, and in the spirit of Hello World, it helps to know how to build parsimonious applications. That is, you should know how to build an application completely from scratch, without five source files and two interface files. Here is a walkthrough showing you exactly that—a very basic Hello World that mirrors the approach shown with the previous Hello World example but that manages to do so with one file and no .storyboard or xib files.

    Start by creating a new project (File > New Project, Command-Shift-N) in Xcode. Choose Empty Application, click Next, enter Hello World as the product name, and set your company identifier as needed (mine is com.sadun). Set the device family to Universal, uncheck Use Core Data, uncheck Include Unit Tests, and click Next. Save it to your desktop.

    When the project window opens, select the two App Delegate files (.h and .m) from the project navigator and click delete or backspace to delete them. Choose Delete (formerly Also Move to Trash) when prompted.

    Open Hello World > Supporting Files > main.m and replace its contents with Listing 3-1. The source is included in the sample code for this book (see the Preface for details), so you don’t have to type it in by hand.

    Listing 3-1  Reductionist main.m

    #import <UIKit/UIKit.h>
    
    // Simple macro distinguishes iPhone from iPad 
    #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)  
    @interface TestBedAppDelegate : NSObject <UIApplicationDelegate> 
    {
         UIWindow *window; 
    } 
    @end  
    
    @implementation TestBedAppDelegate - (UIViewController *) helloController 
    {
         UIViewController *vc = [[UIViewController alloc] init];
         vc.view.backgroundColor = [UIColor greenColor];
    
         // Add a basic label that says "Hello World"
         UILabel *label = [[UILabel alloc] initWithFrame:
             CGRectMake(0.0f, 0.0f, window.bounds.size.width, 80.0f)];
         label.text = @"Hello World";
         label.center = CGPointMake(CGRectGetMidX(window.bounds),
             CGRectGetMidY(window.bounds));
         label.textAlignment = UITextAlignmentCenter;
         label.font = [UIFont boldSystemFontOfSize: IS_IPHONE ? 32.0f : 64.0f];
         label.backgroundColor = [UIColor clearColor];
         [vc.view addSubview:label];
          return vc; 
    }  
    
    - (BOOL)application:(UIApplication *)application
         didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
    {
         window = [[UIWindow alloc] initWithFrame:
             [[UIScreen mainScreen] bounds]];
         window.rootViewController = [self helloController];
         [window makeKeyAndVisible];
         return YES; 
    } 
    @end  
    
    int main(int argc, char *argv[]) {
         @autoreleasepool {
             int retVal =
                 UIApplicationMain(argc, argv, nil, @"TestBedAppDelegate");
             return retVal;
         } 
    }

    So what does this application do? It builds a window, colors the background, and adds a label that says “Hello World.” In other words, it does exactly what the first Hello World example did, but it does so by hand, without using Interface Builder.

    The application starts in main.m by establishing the autorelease pool and calling UIApplicationMain(). From there, control passes to the application delegate, which is specified as the last argument of the call by naming the class. This is a critical point for building a non–Interface Builder project, and one that has snagged many a new iPhone developer.

    The delegate, receiving the application:didFinishLaunchingWithOptions: message, builds a new window, querying the device for the dimensions (bounds) of its screen. It creates a new view controller, assigns that controller as its rootViewController property, and orders it out, telling it to become visible. Using the device’s screen bounds ensures that the main window’s dimensions matches the device. For older iPhones, the window will occupy a 320·480-pixel area, for the iPhone 4 and later, 640·960 pixels, for the first two generations of iPads, 768·1024 pixels.

    The helloController method initializes its view controller’s view by coloring its background and adding a label. It uses UI_USER_INTERFACE_IDIOM() to detect whether the device is an iPhone or iPad, and adjusts the label’s font size accordingly to either 32 or 64 points. In real-world use, you may want to perform other platform-specific adjustments such as choosing art or setting layout choices.

    As you can see, laying out the label takes several steps. It’s created and the text added, centered, aligned, and other features modified. Each of these specialization options defines the label’s visual appearance, steps that are much more easily and intuitively applied in Interface Builder. Listing 3-1 demonstrates that you can build your interface entirely by code, but it shows how that code can quickly become heavy and dense.

    In Xcode, the Interface Builder attributes inspector fills the same function. The inspector shows the label properties, offering interactive controls to choose settings such as left, center, and right alignment. Here, that alignment is set programmatically to the constant UITextAlignmentCenter, the background color is set to clear, and the label programmatically moved into place via its center property. In the end, both the by-hand and Interface Builder approaches do the same thing, but here the programmer leverages specific knowledge of the SDK APIs to produce a series of equivalent commands.

    Browsing the SDK APIs

    iOS SDK APIs are fully documented and accessible from within Xcode. Choose Help > Developer Documentation (Command-Option-Shift-?) to open the Xcode Organizer > Documentation browser. The Documentation tab will be selected at the top bar of the window. Other tabs include iPhone, Repositories, Projects, and Archives, each of which plays a role in organizing Xcode resources.

    The documentation you may explore in this window is controlled in Xcode’s preferences. Open those preferences by choosing Xcode > Preferences (Command-,) > Documentation. Use the GET buttons to download document sets. Keep your documentation up to date by enabling “Check for and install updates automatically.”

    In the Developer Documentation organizer, start by locating the three buttons at the top of the left-hand area. From left to right these include an eye, a magnifying glass, and an open book. The eye links to explore mode, letting you view all available documentation sets. The magnifying glass offers interactive search, so you can type in a phrase and find matching items in the current document set. The open book links to bookmarks, where you can store links to your most-used documents.

    Select the middle (magnifying glass) search button. In the text field just underneath that button locate another small magnifying glass. This second magnifying glass has a disclosure triangle directly next to it. Click that disclosure and select Show Find Options from the pop-up menu. Doing so reveals three options below the text field: Match Type, Doc Sets, and Languages. Use the Doc Sets pop-up to hide all but the most recent iOS documentation set. This simplifies your search results so you do not find multiple hits from SDK versions you’re not actually using.

    Enter UILabel into the search field to find a list of API results that match UILabel, as well as full text and title matches. The first item in the results list should link to the iOS Library version of the documentation. Refer to the jump bar at the top of the main area to locate which library you are viewing. This should read something like iOS Library > User Experience > Windows & Views > UILabel Class Reference. The UILabel Class Reference (see Figure 3-8) displays all the class methods, properties, and instance methods for labels as well as a general class overview.

    Figure 3-8
    Apple offers complete developer documentation from within Xcode itself.

    Apple’s Xcode-based documentation is thorough and clear. With it you have instant access to an entire SDK reference. You can look up anything you need without having to leave Xcode. When material goes out of date, a document subscription system lets you download updates directly within Xcode.

    Xcode 4 lost the handy class overview that appeared to the left of documentation in Xcode 3. The jump bar at the top embeds the same organization features (namely overview, tasks, properties, and so on). If you’d rather view the material with the old-style Developer Library overview, right-click in the class reference area and choose Open Page in Browser. Figure 3-9 shows the browser-based presentation with that helpful at-a-glance class Table of Contents to the left of the core material.

    Figure 3-9
    The “Table of Contents” view is no longer available from within Xcode itself but can be accessed via Open Page in Browser.

    Converting Interface Builder Files to Their Objective-C Equivalents

    A handy open-source utility by Adrian Kosmaczewski allows you to convert Interface Builder files to Objective-C code. With it, you can extract all the layout information and properties of your visual design and see how that would be coded by hand. nib2objc does exactly what its name suggests. With it, you can generate converted code that takes into account the class constructors, method calls, and more. It works on .xib and .storyboard files, although some newer features such as segues are not yet exposed; under the hood both formats are simply XML.

    Listing 3-2 shows the result of running nib2objc on the .xib file used in the first walkthrough. Compare it to the far simpler (and less thorough) by-hand version in Listing 3-1. It performs more or less the same tasks. It creates a new label and then adds the label to the window. However, this conversion utility exposes all the underlying properties, of which just a few were edited in Listing 3-1.

    To peek at the original IB XML, open the storyboard file in Text Edit. Issue open -e from the Terminal command line while in the HelloWorld project folder in the en.lproj subfolder:

    open -e MainStoryboard_iPad.storyboard

    Note - nib2obj is hosted at http://github.com/akosma/nib2objc and issued under a general “Use this for good not evil” style of license.

    Listing 3-2  HelloWorldViewController.xib after Conversion to Objective-C

    UIView *view3 = [[UIView alloc] initWithFrame:
         CGRectMake(0.0, 20.0, 320.0, 460.0)]; 
    view3.frame = CGRectMake(0.0, 20.0, 320.0, 460.0); 
    view3.alpha = 1.000; 
    view3.autoresizingMask =
         UIViewAutoresizingFlexibleRightMargin |
         UIViewAutoresizingFlexibleBottomMargin;
    view3.backgroundColor =
         [UIColor colorWithRed:0.963 green:1.000 blue:0.536 alpha:1.000];
    view3.clearsContextBeforeDrawing = YES; 
    view3.clipsToBounds = NO; view3.contentMode = UIViewContentModeScaleToFill; view3.hidden = NO; view3.multipleTouchEnabled = NO; view3.opaque = YES; view3.tag = 0; 
    view3.userInteractionEnabled = YES;  
    
    UILabel *view6 = [[UILabel alloc] initWithFrame:
         CGRectMake(72.0, 150.0, 175.0, 160.0)]; 
    view6.frame = CGRectMake(72.0, 150.0, 175.0, 160.0); 
    view6.adjustsFontSizeToFitWidth = YES; 
    view6.alpha = 1.000; view6.autoresizingMask =
         UIViewAutoresizingFlexibleLeftMargin |
         UIViewAutoresizingFlexibleRightMargin |
         UIViewAutoresizingFlexibleTopMargin |
         UIViewAutoresizingFlexibleBottomMargin; 
    view6.baselineAdjustment = UIBaselineAdjustmentAlignCenters; 
    view6.clearsContextBeforeDrawing = YES; 
    view6.clipsToBounds = YES; 
    view6.contentMode = UIViewContentModeLeft; v
    iew6.enabled = YES; view6.hidden = NO; 
    view6.lineBreakMode = UILineBreakModeTailTruncation; 
    view6.minimumFontSize = 10.000; 
    view6.multipleTouchEnabled = NO; 
    view6.numberOfLines = 1; view6.opaque = NO; 
    view6.shadowOffset = CGSizeMake(0.0, -1.0); 
    view6.tag = 0; view6.text = @"Hello World"; 
    view6.textAlignment = UITextAlignmentLeft; 
    view6.textColor = [UIColor colorWithRed:0.000 green:0.000 blue:0.000 alpha:1.000]; 
    view6.userInteractionEnabled = NO;  
    
    [view3 addSubview:view6]; 
    [view2 addSubview:view3];

    Using the Debugger

    Xcode’s integrated debugger provides a valuable tool for iPhone application development. This walkthrough shows you where the debugger is and provides a simple grounding for using it with your program. In these steps, you discover how to set breakpoints and use the debugger console to inspect program details. These steps assume you are working on the second, minimalist Hello World example just described and that the project window is open and the main.m file displayed.

    Set a Breakpoint

    Locate the helloController method in the main.m file of your Hello World project. Click in the leftmost Xcode window column, just to the left of the label assignment line. A blue breakpoint indicator appears (see Figure 3-10). The dark blue color means the breakpoint is active. Tap once to deactivate—the breakpoint turns light blue—and once more to reactivate.

    Figure 3-10
    Blue breakpoint indicators appear in the gutter to the left of the editor area. You can reveal the debugger at the bottom of the workspace by clicking the Debugger disclosure button while running an application or by clicking the center of the three View buttons at the top-right of the workspace window at any time.

    Remove breakpoints by dragging them offscreen or right-clicking them; add them by clicking in the column, next to any line of code. Once added, your breakpoints appear in the workspace’s Breakpoint Navigator (Command-6). You can delete breakpoints from the navigator (select, then press the Delete button) and can deactivate and reactivate them from there as well.

    Open the Debugger

    Compile the application (Product > Build, Command-B) and run it (Product > Run, Command-R). The simulator opens, displays a black screen, and then pauses. Execution automatically breaks when it hits the breakpoint. A green bar appears next to your breakpoint, with the text “Thread 1: Stopped at breakpoint 1.”

    In Xcode, the debugging pane appears automatically as you run the application. You can reveal or hide it manually by clicking the middle of the three View buttons at the top-right of the workspace window; it looks like a rectangle with a dark bottom. When the debugger is shown, you can drag its jump bar (not the one at the top of the editor window, but the one at the top of the debugger) upward to provide more room for your output.

    The debugger provides both a graphical front end for inspecting program objects as well as a text-based log area with an interactive debugger console. Xcode offers two command-line debuggers: gdb and lldb. The LLDB project (hosted at http://llvm.org) expands upon the standard GNU debugger (gdb) with improved memory efficiency and Clang compiler integration.

    Select which debugger you wish to use by editing your project scheme, as shown in Figure 3-11. Select Edit Scheme from the pop-up at the left of your toolbar at the top of your workspace window just to the right of the Run and Stop buttons. (Make sure you’re selecting the Hello World part of the pop-up, not the iPhone or iPad simulator part.) Use the Info > Debugger pop-up to switch between GDB and LLDB. Click OK.

    Figure 3-11
    The project scheme editor allows you to select which debugger you prefer to use.

    Inspect the Label

    Once stopped at the breakpoint, the interactive debugger and the debugger command line let you inspect objects in your program. Using lldb, you can look at the label by typing print-object label or, more simply po label at the command line. Use print or p to print non-objects, such as integer values.

    (lldb) po label 
    (UILabel *) $3 = 0x06a3ded0 <UILabel: 0x6a3ded0; frame = (0 0; 320 80); 
    clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x6a3df40>>

    At this time, the label’s text has not yet been set and it has not yet been added to the view controller’s view. You can confirm that the label is not yet added to the view by looking at the view controller’s view’s subviews, currently an empty array, and the label’s superview, currently nil.

     (lldb) po [[vc view] subviews] 
    (id) $4 = 0x06811e20 <__NSArrayI 0x6811e20>(  
    
    )  (lldb) po [label superview] 
    (id) $5 = 0x00000000 <nil> 
    (lldb)

    You can also view the label directly using the inspector at the left side of the debugger. Locate label and click the disclosure triangle to the left of it to show the properties of the label object. The label’s _text field is set to <nil>.

    The Step Into button appears to the left of the debugger jump bar. It looks like an arrow pointing down to a small black line. Click it once. The text assignment executes and the green arrow moves down by one line. The summary of the label.text updates. It should now say something like “Hello World (iPhone).” Confirm by inspecting the label from the command line by typing po label again. The label has updated its text instance variable to Hello World.

    (lldb) po label (UILabel *) $12 = 0x06a3ded0 <UILabel: 0x6a3ded0; frame = (0 0; 320 80); text = 'Hello World'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x6a3df40>>

    If you want to get really crazy, you can override values directly by using p or print to make interpreted calls during the execution of your application. This call changes the label text from “Hello World” to “Bye World.” It does that by executing the items within the square brackets, casting the void return to an integer, and then printing the (meaningless) results.

    (lldb) p (int)[label setText:@"Bye World"] 
    (int) $13 = 117671936 
    (lldb) po label (UILabel *) $14 = 0x06a3ded0 <UILabel: 0x6a3ded0; frame = (0 0; 320 80); 
    text = 'Bye World'; 
    clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 
    0x6a3df40>>

    Set Another Breakpoint

    You can set additional breakpoints during a debugging session. For example, add a second breakpoint just after the line that sets the text alignment to center, on the line that sets the background color. Just click in the gutter next to label.backgroundColor, or wherever you want to set the breakpoint.

    Confirm that the current alignment is set to 0, the default value, by inspecting the label’s textLabelFlags—you will have to open the disclosure triangles in the column to the left of the lldb interface to see these label attributes. With the new breakpoint set, click the Resume button. It appears as a right-pointing triangle with a line to its left.

    HelloWorld resumes execution until the next breakpoint, where it stops. The green arrow should now point to the backgroundColor line, and the explicit alignment flag updates from 0 to 1 as that code has now run, changing the value for that variable.

    (lldb) p (int) [label textAlignment] 
    (int) $19 = 1

    You can further inspect items by selecting them in the left-hand debugging inspector, right-clicking, and choosing Print Description from the contextual pop-up menu. This sends the description method to the object and echoes its output to the console.

    Note - Remove breakpoints by dragging them out from the left column or by deleting them in the Breakpoint Navigator.

    List your breakpoints by issuing the breakpoint list command. Lldb prints out a list of all active breakpoints.

    (lldb) breakpoint list 
    Current breakpoints: 
    1: file ='main.m', line = 26, locations = 1, resolved = 1 
    baton: 0x11b2dd380   
    1.1: where = Hello World`-[TestBedAppDelegate helloController] + 365 at 
    main.m:26,
       address = 0x0000211d, resolved, hit count = 1  
    
    3: file ='main.m', line = 30, locations = 1, resolved = 1 
    baton: 0x12918d6c0
       3.1: where = Hello World`-[TestBedAppDelegate helloController] + 912 at main.m:30,
       address = 0x00002340, resolved, hit count = 0

    Note - Learn more about setting and controlling breakpoints by visiting the LLVM website. The official lldb tutorial is found at lldb.llvm.org/tutorial.html.

    Backtraces

    The bottom pane of the debugging window offers text-based debugger output that can mirror results from other panes. For example, open the Debug Navigator and view the application by thread, disclosing the trace details for Thread 1. This provides a trail of execution, showing which functions and methods were called, in which order to get you to the current point where your application is.

    Next, type backtrace or bt at the text debugger prompt to view the same trace that was shown in that navigator. After stopping at the second breakpoint, the backtrace should show that you are near (for example, line 26 in the source from main.m). You will see this line number toward the beginning of the trace, with items further back in time appearing toward the end of the trace. This is the opposite of the view shown in the Debug Navigator, where more recent calls appear toward the top of the pane.

    Console

    This bottom text-based debugger is also known as the console. This pane is where your printf, NSLog, and CFShow messages are sent by default when running in standard debug mode or when you use the simulator. You can resize the console both by adjusting the jump bar up or down and also by dragging the resize bar between the left and right portions of the debugger. If you want, you can use the show/hide buttons at the top-right of the debugger. Three buttons let you hide the console, show both the console and the visual debugger, or show only the console. To the left of these three buttons is a Clear button. Click this to clear any existing console text.

    To test console logging, add a NSLog(@"Hello World!"); line to your code; place it after adding the label as a window subview. Remove any existing breakpoints and then compile and run the application in the simulator. The log message appears in the Debug area’s console pane. The console keeps a running log of messages throughout each execution of your application. You can manually clear the log as needed while the application is running.

    Add Simple Debug Tracing

    If you’re not afraid of editing your project’s .pch file, you can add simple tracing for your debug builds. Edit the file to add the following macro definition:

    #ifdef DEBUG
         #define DebugLog(...) NSLog(@"%s (%d) %@", __PRETTY_FUNCTION__, __LINE__,
         [NSString stringWithFormat:__VA_ARGS__]) 
    #else
         #define DebugLog(...) 
    #endif

    Memory Management

    iOS does not offer garbage collection. It relies on a reference counted memory management system. The new LLVM ARC extensions introduce automated reference counting, letting the compiler take care of many management issues for you. ARC automates when objects are retained and released, simplifying development. That doesn’t mean you don’t have to worry about memory:

    • Even with ARC, you remain responsible for letting go of resources that create low-memory conditions. If you hold onto lots of multimedia assets such as video, audio, and images, you can exhaust memory—even in ARC-compiled applications.
    • Many developers continue to use manual retain/release (MRR) development, especially to avoid refactoring production-critical code. Using MRR means you must control when objects are created, retained, and released in that code because ARC will not handle that for you.
    • ARC does not automatically extend to Core Foundation and other C-based class code. Even if CF classes are toll-free bridged, ARC does not assume control of their instances until they are bridged into the Objective-C world.

    As a developer, you must strategize how to react to low-memory conditions. Use too much memory and the iPhone warns your application delegate and UIViewControllers. Delegates receive applicationDidReceiveMemoryWarning: callbacks; view controllers get didReceiveMemoryWarning. Continue to use too much memory and the iPhone will terminate your application, crashing your user back to the iOS home screen. As Apple repeatedly points out, this is probably not the experience you intend for your users, and it will keep your application from being accepted into the App Store.

    You must carefully manage memory in your programs and release that memory during low-memory conditions. Low memory is usually caused by one of two problems: leaks that allocate memory blocks that can’t be accessed or reused, and holding onto too much data at once. Even on newer iOS devices, such as the iPad 2, your application must behave itself within any memory limits imposed by the operating system.

    Every object in Objective-C is created with an integer-based retain count. So long as that retain count remains at 1 or higher, objects will not be deallocated. That rule applies in ARC code just as it applies in MRR. It is up to you as a developer to implement strategies that ensure that objects get released at the time you will no longer use them.

    Every object built with alloc, new, or copy starts with a retain value of 1. Whether developing with ARC or MRR, if you lose access to an object without reducing the count to 0, that lost object creates a leak (that is, memory that is allocated and cannot be recovered). The following code leaks an array:

    NSArray *leakyArray = [NSArray arrayWithObjects:@"Hello", @"World", nil]; 
    CFArrayRef leakyRef = (__bridge_retained CFArrayRef) leakyArray; 
    leakyRef = nil;

    Recipe: Using Instruments to Detect Leaks

    Instruments plays an important role in tuning your applications. It offers a suite of tools that lets you monitor and evaluate performance. For example, its leak detection lets you track, identify, and resolve memory leaks within your program. Recipe 3-1 shows an application that creates two kinds of leaks on demands: one created by using CF bridging without a proper release, the other by introducing a strong reference cycle that cannot be resolved by ARC at the termination of its method.

    To see Instruments in action, load the sample project for Recipe 3-1. Choose one of the simulator options as your destination from the leftmost pop-up in the toolbar at the top of your workspace, just to the right of the Run and Stop buttons. Then click and hold the Run button until the pop-up shown in Figure 3-12 appears. Choose Profile and then agree to whatever impediments Xcode throws in your direction (if any), such as stopping any currently running application, and so on.

    Figure 3-12
    Select Profile from the Run button’s pop-up.

    Instruments launches and asks you to select a Trace Template. Choose iOS Simulator > Leaks and then click Profile. Instruments opens a new profiling window, launches the application in the simulator, and starts running. Click the Stop button at the top-left of the Instruments window. There are some adjustments you’ll want to make.

    In the left-hand column, under the individual Instruments traces, you’ll see an item labeled “Allocations.” It is just below a slider and just above the Heapshot Analysis. This is a pop-up, as indicated by the arrows to its right. Use the pop-up to change from Allocations to Leaks.

    With Leaks selected, the first item is now Snapshots. Change the Snapshot Interval from 10 seconds to 1. This lets you see updates in “real” time; even so, be patient. Instruments detects leaks during its snapshots, with a slight lag after performing the snapshot.

    You are now ready to start a fresh trace. Click Record. The application relaunches in the simulator. With Instruments and the simulator both running, click one of the two buttons in the title bar to leak memory:

    • The CF Bridging button leaks a simple 16-byte NSArray.
    • The Retain Cycle button leaks two 16-byte NSArray objects that are connected to each other via a retain cycle, for a total of 32 bytes.

    Memory leaks appear in Instruments as orange markers, scaled to the size of the leaks. The Leaked Blocks pane appears at the bottom of the window, as shown in Figure 3-13, once you click the Leaks trace row at the top of the window.

    Figure 3-13
    Instruments tracks leaks created by memory blocks that cannot be addressed or recovered by your code.

    The trace shown in Figure 3-13 presents two leak events. The first orange marker corresponds to tapping the Retain Cycle button; the second to CF Bridging. The responsible frame for the first leak is shown to be the leakArrayRetainCycle method. A stack trace appears in the extended detail pane on the right side of the view. This pane is shown or hidden using the rightmost of the three View buttons at the top toolbar of the Instruments window. My “Hello World” code is noted to be the responsible library for both of the leaks, allowing me to further recognize that the leaked memory originated in my code.

    Note - When working with possible retain cycles, use the jump bar in the center of the window (the quartered square followed by the word “Leaks” in Figure 3-13) to choose Cycles. This is a feature that Apple is still evolving. During the time this book was being written (that is, the beta period), it functioned less and crashed more. Hopefully Apple will finish refining this potentially valuable feedback before the iOS 5 beta goes golden.

    Recipe 3-1  Creating Programmatic Leaks

    - (void) leakArrayRetainCycle {
         NSMutableArray *array1 = [NSMutableArray array];
         NSMutableArray *array2 = [NSMutableArray array];
         [array1 addObject:array2];
         [array2 addObject:array1]; 
    }  
    
    - (void) leakArrayCFBridge 
    {
         NSArray *array = [NSArray arrayWithObjects:
             @"Hello", @"World", nil];
         CFArrayRef leakyRef = (__bridge_retained CFArrayRef) array;
         leakyRef = NULL; 
    }

    Get This Recipe’s Code - To get the code used for this recipe, go to https://github.com/erica/iOS-5-Cookbook, or if you've downloaded the disk image containing all the sample code from the book, go to the folder for Chapter 3 and open the project for this recipe.

    Recipe: Using Instruments to Monitor Cached Object Allocations

    When you load too much data at once, you can also run short of memory. Holding onto everything in your program when you are using memory-intense resources such as images, audio, or PDFs may cause problems. A strategy called caching lets you delay loads until resources are actually needed and release that memory when the system needs it.

    The simplest approach involves building a cache from an NSMutableDictionary object. A basic object cache works like this: When queried, the cache checks to see whether the requested object has already been loaded. If it has not, the cache sends out a load request based on the object name. The object load method might retrieve data locally or from the Web. After the data is loaded, the cache stores the new information in memory for quick recall.

    This code performs the first part of a cache’s duties. It delays loading new data into memory until that data is specifically requested. (In real life, you probably want to type your data and return objects of a particular class rather than use the generic id type.)

    - (id) retrieveObjectNamed: (NSString *) someKey {
         id object = [self.myCache objectForKey:someKey];
         if (!object)
         {
             object = [self loadObjectNamed:someKey];
             [self.myCache setObject:object forKey:someKey];
         }
         return object;
    }

    The second duty of a cache is to clear itself when the application encounters a low-memory condition. With a dictionary-based cache, all you have to do is remove the objects. When the next retrieval request arrives, the cache can reload the requested object.

    - (void) respondToMemoryWarning 
    {
         [self.myCache removeAllObjects]; 
    }

    Combining the delayed loads with the memory-triggered clearing allows a cache to operate in a memory-friendly manner. Once objects are loaded into memory, they can be used and reused without loading delays. However, when memory is tight, the cache does its part to free up resources that are needed to keep the application running.

    Simulating Low-Memory Conditions

    One feature of the simulator allows you to test how your application responds to low-memory conditions. Selecting Hardware > Simulate Memory Warning sends calls to your application delegate and view controllers, asking them to release unneeded memory. Instruments, which lets you view memory allocations in real time, can monitor those releases. It ensures that your application handles things properly when warnings occur. With Instruments, you can test memory strategies such as caches, discussed earlier in this chapter.

    Recipe 3-2 creates a basic object cache. Rather than retrieve data from the Web or from files, this cache builds empty NSData objects to simulate a real-world use case. When memory warnings arrive, as shown in Figure 3-14, the cache responds by releasing its data.

    Figure 3-14
    Instruments helps monitor object allocations, letting you test your release strategies during memory warnings.

    The stair-step pattern shown here represents four memory allocations created by pressing the Consume button while using Instrument’s Allocation profiler. After, the simulator issued a memory warning. In response, the cache did its job by releasing the images it had stored. The memory then jumped back down to its previous levels.

    Instruments lets you save your trace data, showing the application’s performance over time. Stop the trace and then choose File > Save to create a new trace file. By comparing runs, you can evaluate changes in performance and memory management between versions of your application.

    Some SDK objects are automatically cached and released as needed. The UIImage imageNamed: method retrieves and caches images in this manner, as does the UINib nibWithNibName:bundle:, which preloads NIBs into a memory cache for faster loading. When memory grows low, these classes empty their caches to free up that memory for other use.

    Recipe 3-2  Object Cache Demo 
    @implementation ObjectCache 
    @synthesize myCache, allocationSize;
    // Return a new cache + (ObjectCache *) cache 
    {
         return [[ObjectCache alloc] init]; 
    }  
    // Fake loading an object by creating NSData of the given size 
    - (id) loadObjectNamed: (NSString *) someKey 
    {
         if (!allocationSize) 
         // pick your allocation size    
         allocationSize = 1024 * 1024;
         char *foo = malloc(allocationSize);
         NSData *data = [NSData dataWithBytes:foo length:allocationSize];
         free(foo);
         return data; 
    }  
    // When an object is not found, it's loaded 
    - (id) retrieveObjectNamed: (NSString *) someKey 
    {
         if (!myCache)
             self.myCache = [NSMutableDictionary dictionary];
         id object = [myCache objectForKey:someKey];
         if (!object)
         {
             if ((object = [self loadObjectNamed:someKey]))
                 [myCache setObject:object forKey:someKey];
         }     return object; 
    }  
    // Clear the cache at a memory warning 
    - (void) respondToMemoryWarning 
    {
         [myCache removeAllObjects]; 
    } 
    @end

    Get This Recipe’s Code - To get the code used for this recipe, go to https://github.com/erica/iOS-5-Cookbook, or if you've downloaded the disk image containing all the sample code from the book, go to the folder for Chapter 3 and open the project for this recipe.

    Analyzing Your Code

    The LLVM/Clang static analyzer automatically helps detect bugs in Objective-C programs. It’s a terrific tool for finding memory leaks and other issues, especially with Core Foundation and MRR code. In Xcode, choose Product > Analyze (Command-Control-B). The issue markers shown in Figure 3-15 guide you through all suspected leaks and other potential problems. Use the Issue Navigator pane to dive into each issue and walk through the logic that leads the analyzer to raise a flag of concern.

    Figure 3-15
    The Clang static analyzer creates bug reports for source code and embeds them into your Xcode editor window. Clang is useful for both MRR (as shown here) and ARC and provides reports specific to each compilation style.

    Issues found by the static analyzer are not necessarily bugs. It’s possible to write valid code that Clang identifies as incorrect. Always critically evaluate all reported issues before making any changes to your code.

    From Xcode to Device: The Organizer Interface

    Choose Window > Organizer (Command-Shift-2) to open the Xcode Organizer window shown in Figure 3-16. This window forms the control hub for access between your development computer and your iOS testbed. It allows you to manage your credentials, add and remove applications, examine crash logs, and snap screenshots of your unit while testing your application.

    Figure 3-16
    Xcode’s Organizer window provides a central hub for managing your devices, certificates, and provisions.

    The Organizer consists of two primary sections, the Library and the Devices, which have overlapping functionality. The library offers what is, basically, a merged inbox of device logs, provisioning profiles, and screenshots. These are broken out on a per-device basis in the Devices section.

    In addition, the library has a Developer Profile section for organizing your developer certificates and a Software Images section for managing firmware bundles. The Devices list adds per-device consoles and per-device application management.

    Devices

    The Devices list shows the name and status of those devices you’ve authorized as development platforms. The indicators to the right of each name show whether the device is attached (green light) or not (white light). A blank to the right of the device name indicates a unit that has not been set up for development or that has been “ignored”—that is, removed from the active list. An amber light appears when a device has just been attached. Should the light remain amber colored, you may have encountered a connection problem. This may be due to iTunes syncing, and the unit is not yet available, or there may be a problem connecting with the onboard services, in which case a reboot of your iOS device usually resolves any outstanding issues.

    A disclosure button appears to the left of each device, offering access to device information specific to that device. The items you find here mirror many of those listed in the Library section of the Organizer, including device logs, screenshots, and provisioning profiles. In addition, you have access to the device console and an application list.

    Summary

    Selecting a device name offers an overview of that device, including the capacity, serial number, and identifier of your unit. Here is also where you can load the latest firmware onto a device. Select a firmware version from the software pop-up and click Restore. Other items on this screen include overviews of current provisions, applications, device logs, and screenshots.

    Be warned. Device downgrades are not always possible when you’ve upgraded to a newer (especially beta) iOS version. Downgrades must be authorized by Apple’s signature servers, even when you have stored the older firmware locally on your computer. These servers allow Apple to control which older firmware they will and will not allow to be installed, essentially providing them with a rolling firmware recall system that disallows older firmware over time.

    Provisioning Profiles

    Each developer license allows you to provision your personal or corporate iOS devices for testing. The Provisioning list shows a list of application provisions available to your unit. You can add or delete provisions from this screen.

    Provisions determine which applications may or may not be run on the device. As a rule, only development and ad hoc distribution provisions are listed here, which makes sense. Distribution provisions are used to sign applications for the App Store, not for any specific device.

    Device Logs

    Get direct access to your crash logs by selecting a particular crash (labeled with the application name and the date and time of the crash) from the scrolling list on this screen. The crash details, including a stack trace, thread information, exception types, and so forth, appear in the right-hand pane. You can import and export logs using the buttons on this screen.

    In addition to crash logs that you generate yourself, you can also retrieve crash reports from users from their home computer and from iTunes Connect. The iPhone automatically syncs crash reports to computers when units back up to iTunes. These reports are stored in different locations depending on the platform used to sync the device:

    • Mac OS X—/Users/UserName/Library/Logs/CrashReporter/MobileDevice/ DeviceName
    • Windows XP—C:\Documents and Settings\UserName\Application Data\Apple Computer\Logs\CrashReporter\MobileDevice\DeviceName
    • Windows Vista—C:\Users\UserName\AppData\Roaming\Apple Computer\Logs\CrashReporter\MobileDevice\DeviceName

    iTunes Connect collects crash log data from your App Store users and makes it available to you. Download reports by selecting Manage Your Applications > App Details > View Crash Report for any application. There you find a list of the most frequent crash types and Download Report buttons for each type.

    Copy reports into the Mac OS X crash reporter folder and they load directly into the Organizer. Make sure to load them into the device folder for the currently selected device. The reports appear in LIBRARY > Device Logs.

    Once in the Organizer, Xcode uses the application binary and .dSYM file to replace the hexadecimal addresses normally supplied by the report with function and method names. This process is called “symbolication.” You don’t have to manually locate these items; Xcode uses Spotlight and the application’s unique identifier (UID) to locate the original binary and .dSYM files so long as they exist somewhere in your home folder. Xcode’s archive feature offers the best way to keep these materials together and persistently available.

    As with crash logs in the Organizer, the reports from users provide a stack trace that you can load into Xcode to detect where errors occurred. The trace always appears in reverse chronological order, so the first items in the list were the last ones executed.

    In addition to showing you where the application crashed, Crash Reports also tell you why they crashed. The most common cause is EXC_BAD_ACCESS, which can be generated by accessing unmapped memory (KERN_INVALID_ADDRESS) or trying to write to read-only memory (KERN_PROTECTION_FAILURE).

    Other essential items in the crash report include the OS version of the crash and the version of the application that crashed. Users do not always update software to the latest release, so it’s important to distinguish which crashes arose from earlier, now potentially fixed, versions.

    Note - See Apple Technical Note TN2151 for more details about iOS crash reporting.

    Applications

    Each device offers a browseable list of installed applications. Use the – button to remove selected applications. To install an application, drag it onto the list or use the + button to browse for it. Make sure your application is compiled for iOS and that the device is provisioned to run that application. If you self-sign an application and install it to a device—the how-to process for doing so is described later in this chapter—your application uses your team provision. When added, applications immediately sync over to the device. Applications installed from the App Store do not appear in the application list any more, the way they did in Xcode 3.

    To download the data associated with an application, click the Download button to the right of its name. Choose a destination and click Save. Xcode builds an archive bundle and populates it with the contents of the sandbox—namely the Documents, Library, and tmp directories. Xcode also adds the folder to the Projects and Sources list, where you can browse the contents directly from the Organizer.

    You can reverse this process and add edited sandboxes back to the device. Locate the bundle you created. Drop new items into any of the enclosed subfolders and then drag the entire folder back onto the application name at the bottom of the Summary pane. Xcode reads the new items and instantly transfers them to the device. This is a great way to prepopulate your sandbox with test material.

    Console

    Use the console to view system messages from your connected units. This screen shows NSLog() calls and other messages sent to stderr (standard error output) as you’re running software on the tethered iPhone. You need not be using Xcode’s debugger to do this. The console listens in to any application currently running on the device.

    In addition to the debugging messages you add to your iPhone applications, you also see system notices, device information, and debugging calls from Apple’s system software. It can be viewed as basically a text-based mess, but there’s a lot of valuable information you can gain. Click Save Log As to write the console contents out to disk or click Clear to empty the Console backlog.

    Screenshots

    Snapshot your tethered iPhone’s screen by clicking the New Screenshot button on the Screenshot display. The screenshot feature takes a picture of whatever is running on the iPhone, whether or not your applications are open. So you can access shots of Apple’s built-in software and any other applications running on the iPhone.

    Once snapped, images can be dragged onto the desktop or saved as an open project’s new Default.png image (“Save as Launch Image”). Archival shots appear in a library on the left side of the window. To delete a screenshot, select one and press the Delete key to permanently remove it. Other features on this screen allow you to export images and compare images to highlight differences between separate shots.

    Note - Screenshots are stored in your home Library/Application Support/Developer/Shared/Xcode/Screenshots folder.

    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.

    Detecting Simulator Builds with Compile-Time Checks

    Xcode directives issue instructions to the compiler that can detect the platform you’re building for. This lets you customize your application to safely take advantage of device-only features when they’re available. Adding #if statements to your code lets you block or reveal functionality based on these options. To detect if your code is compiled for the simulator or for an iOS device, use a compile-time check:

    #if TARGET_IPHONE_SIMULATOR     Code specific to simulator #else     Code specific to iPhone #endif

    Performing Runtime Compatibility Checks

    There is a real and measurable adoption lag among iOS device users. To sell your application to the greatest number of customers, do not build for any SDK higher than your lowest desired customer. Use common sense when picking that SDK. You may find it best to support the most recent firmware dot release that lags a few weeks or months behind the latest iOS update, or you may want to extend support to all versions of the current iOS firmware.

    The hardest decisions come when iOS moves forward to a new version. That’s when the adoption rate slows down the most. The 3.x/4.x overlap lasted for some time before developers gained confidence in moving forward to 4.x-only releases. iOS 5 and its successors continue that challenge.

    To build for a range of possible deployment targets, set your Base SDK to the highest version of the OS you want to target—usually the current SDK release. Set your iOS deployment target to the lowest OS version you intend to build for.

    When compiling to a deployment target that is earlier than your base SDK, you’ll need to perform runtime checks for any classes or API calls that might not yet have been introduced to a given firmware platform. For example, an iOS 5-introduced API call will not be available on an iOS 4.2 installation. The following tests allow you to check at runtime for classes and methods that may or may not be available depending on the deployment platform:

    • Check platform geometry—Introduced in iOS 3.2, the idiom check lets you determine if your code is running on an iPhone-like unit (iPhone, iPod touch) or on an iPad. I have not included extensions here to see whether the check itself is implemented simply because I cannot recommend deploying to pre-3.2 platforms anymore. As of the Summer of 2011, 3.x platforms made up only about 5% of all iOS installations. Pre-3.2 installs were a vanishingly small percentage of that.
    • if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) . . .
    • Check deployment platform—Use the model property of the UIDevice class to determine whether the unit is running on an @"iPhone", if ([[UIDevice currentDevice].model isEqualToString:@"iPad"]) . . .
    • Check system prefix—It’s not the best way to approach coding (checking classes and instances directly is far more reliable), but you can check the current system version directly.
    • if ([[[UIDevice currentDevice] systemVersion] hasPrefix:@"5."])  . . .
    • Check for properties using key-value coding—You can determine whether an object offers a value for a given key within the current scope, which allows you to test for properties.
    • UILabel *label = (UILabel *)[cell valueForKey:@"textLabel"]; if (label) [label setText:celltext];
    • Check for class existence—If a class may not exist on a given deployment target, use NSClassFromString() to test whether the class can be produced from its name. Pass it an NSString, such as the following:
    • if (NSClassFromString(@"NSAttributedString")) . . .
    • Check for function existence—You can test for functions before attempting to call them.
    • if(&UIGraphicsBeginImageContextWithOptions != NULL) . . .
    • Check for selector compliance—You can test objects to see whether they respond to specific selectors. When newer APIS are supported, objects will report that they respond to those selectors, letting you call them without crashing the program. You may generate compile-time warnings about unimplemented selectors unless you use workarounds such as performSelector:withObject:. If you really want to go hard core, you can build NSInvocation instances directly, as discussed in Chapter 3.
    if ([cell respondsToSelector:)]) . . .

    Pragma Marks

    Pragma marks organize your source code by adding bookmarks into the method list pop-up button at the top of each Xcode window. This list shows all the methods and functions available in the current document. Adding pragma marks lets you group related items together, as shown in Figure 3-22. By clicking these labels from the drop-down list, you can jump to a section of your file (for example, to Utility or RAOP) as well as to a specific method (such as -hexStringFromBytes:).

    Figure 3-22
    Use pragma marks to organize your method and function list.

    To create a new bookmark, add a pragma mark definition to your code. To replicate the first group in Figure 3-22, for example, add the following:

    #pragma mark Class

    You can also add a separation line with a single dash. This uses a shortcut to add a spacer plus a mark:

    #pragma mark –

    or

    #pragma mark – Marker Title

    The marks have no functionality and otherwise do not affect your code. They are simply organizational tools you choose to use or not.

    Collapsing Methods

    When you need to see more than one part of your code at once, Xcode lets you close and open method groups. Place your mouse in the gutter directly to the left of any method. A pair of disclosure triangles appears. Click a triangle, and Xcode collapses the code for that method, as shown in Figure 3-23. The ellipsis indicates the collapsed method. Click the disclosure triangle, and Xcode reveals the collapsed code. You can also collapse any compound statement.

    Figure 3-23
    Xcode lets you collapse individual methods and functions. This allows you to see parts of your program that normally would not fit onscreen together.

    Preparing for Distribution

    Building for distribution means creating a version of your application that can be submitted to Apple for sale in the App Store. Before you begin submitting, know how to clean up builds, how to edit and use schemes, and how create an archive of your application. You want to compile for the App Store with precision. Cleaning first, then compiling for distribution helps ensure that your applications will upload properly. Archiving produces an application bundling that can be shared and submitted. The section covers these skills and others used with distribution compiles.

    Locating and Cleaning Builds

    Xcode 4 uses a new approach to build code and store built products. In Xcode 3, compiled code was added to a “build” subfolder in your project folder. In Xcode 4, applications are created in your home library by default, in ~/Library/Developer/Xcode/DerivedData. You can locate the built product by selecting it in Project Navigator in the Products group. Right-click the application and choose Show in Finder. Project Archives, which are used for building products that are shared with others or submitted to the App Store, are stored in ~/Library/Developer/Xcode/ Archives.

    Cleaning your builds forces every part of your project to be recompiled from scratch. Performing a clean operation also ensures that your project build contains current versions of your project assets, including images and sounds. You can force a clean by choosing Product > Clean (Command-Shift-K).

    Apple recommends cleaning before compiling any application for App Store review, and it’s a good habit to get into.

    Using Schemes and Actions

    In Xcode, schemes store project build settings. They specify what targets to build, what configuration options to apply, and how the executable environment will be set up. Actions are individual tasks that you can perform to create builds as well as to test, profile, analyze, and archive your application.

    Each scheme consists of a project and a destination. Figure 3-24 shows the scheme pop-up for the Hello World project from this chapter. Access this pop-up by selecting Hello World to the right of the Run button. This is a funny kind of pop-up in that it’s actually split. Clicking to the left or the right of the embedded chevron provides two slightly different menus.

    Figure 3-24
    The scheme pop-up menu consists of schemes and their run destinations, followed by management options.

    Clicking the left produces the pop-up shown in Figure 3-24. This pop-up includes a list of schemes (just one here) and their possible run destinations. Here, destinations include the device and four simulator styles (iPhone and iPad, for iOS 4.3 and iOS 5.0). Following the scheme list is a menu line followed by three options to edit, create, and manage schemes.

    Clicking the right shows only the destination submenu, allowing you to pick a destination for the current scheme. Destinations include any provisioned and development-enabled iOS devices as well as all possible simulator choices for your deployment build settings.

    Note - The plural of scheme in Xcode is schemes, not schema or schemata. As iOS developer Nate True puts it, “It’s schemata non grata” in Xcode.

    With your scheme selected, choose Edit Scheme from the pop-up menu to see a list of available actions. Figure 3-25 shows the actions associated with the Hello World scheme from Figure 3-24. Each action represents an individual development task. They include the following:

    • Build—Building the code
    • Run—Running the compiled code on a device or in the simulator
    • Test—Using Xcode unit test tools that help stress application features
    • Profile—Running the code with live sampling using Instruments
    • Analyze—Applying the static analyzer to unresolved issues
    • Archive—Preparing the application for sharing or submission to the App Store

    Use this scheme editor to customize how each action works in Xcode. For example, in the Run action shown in Figure 3-25, the debugger is set to LLDB. You can easily change this to GDB by selecting it from the pop-up.

    Figure 3-25
    The actions list for a scheme offer a set of tasks that may need to be performed during the creation of an application.

    You’ve already seen the action menu in the Instruments walkthrough earlier in this chapter. Access it by clicking and holding the Run menu at the top-left corner of the Xcode window. Select the action you want to perform from the pop-up. The Run button updates to show the new action item.

    Adding Build Configurations

    Build configurations allow you to specify how your application should be built. They act as a quick reference to the way you want to have everything set up, so you can be ready to compile for your device or for the App Store just by selecting a configuration. They also are useful for adding instrumentation and conditional compilation. Standard Xcode projects offer Debug and Release configurations. You may want to create a few others, such as one for ad hoc distribution.

    Configurations are created and managed on the PROJECT > project name > Info screen in the Configurations section (see Figure 3-26). Assuming you’ve been following along in this chapter, you have already set up the HelloWorld project and edited its debug build settings. It uses your team wildcard provision to sign the application. Instead of editing the build settings each time you want to switch the signing provision, you can create a new configuration instead. Typical configuration options include which architectures you wish to build for and your default code-signing identity.

    Figure 3-26
    Use the Info > Configurations pane to create new configurations so you can build with preset options such as signing identities.

    In the following sections, you’ll read about adding an ad hoc configuration to your project. This is really for example purposes only—because I cannot really think of many other ways you’d want to change build settings for ad hoc versus App Store and because you can pick your signing identity in the Organizer when creating bundles for both destinations. Adapt this example and its steps for your real-world requirements.

    Note - You can distinguish your ad hoc configuration build by using a different bundle ID, product name, or by adding extra alerts, to make it easier to run along the App Store version. Use #ifdef directives to distinguish ad hoc code changes.

    About Ad Hoc Distribution

    Apple allows you to distribute your applications outside the App Store via ad hoc distribution. With ad hoc, you can send your applications to up to 100 registered devices and run those applications using a special kind of mobile provision that allows the applications to execute under the iPhone’s FairPlay restrictions. Ad hoc distribution is especially useful for beta testing and for submitting review applications to news sites and magazines.

    The ad hoc process starts with registering devices. Use the iPhone Developer Program portal to add device identifiers (Program Portal, Devices) and names to your account. Recover these identifiers from the iPhone directly (use the UIDevice class), from Xcode’s Organizer (copy the identifier from the overview tab), from iTunes (click on Serial Number in the iPhone’s Summary tab), or via the free Ad Hoc Helper application available from iTunes. Enter the identifier and a unique username.

    To create a new ad hoc configuration, create a new provision at the iOS portal. Select Program Portal > Provisioning > Distribution. Click Add Profile. Select Ad Hoc, enter a profile name, your standard wildcard application identifier (for example, com.yourname.*), and select the device or devices to deploy on. Don’t forget to check your identity and then click Submit and wait for Apple to build the new mobile provision. Download the provision file and drop it onto the Xcode application icon.

    With your new provision on hand, duplicate the Release configuration. Xcode creates a copy and opens a text entry field for its name. Edit the name from Release copy to Ad Hoc.

    Next, click the Build Settings tab and locate the Code Signing section. Assign your new ad hoc provision to your ad hoc configuration. Use the pop-up to the right of Any iOS SDK. The selected provision then appears in the Code Signing Identity list, as shown in Figure 3-27.

    Figure 3-27
    New configurations appear separately in the Code Signing section of your build settings.

    To finish, choose your new build configuration in the Archive action section of the Scheme editor.

    Note - In addition to adding new configurations by hand, you can also use build configuration files that contain setting definitions in text format. Create these files by selecting File > New > New File > Other > Configuration Settings. You can read more about creating configuration files in Apple’s Xcode Build System Guide.

    Building Ad-Hoc Packages

    1. When you’re ready to share your app with members of your ad hoc list, follow these steps:
    2. If you wish to use a custom compiler scheme, choose Edit Scheme from the Scheme pop-up at the top of the Xcode window. Select Archive and set your Build Configuration as desired. Click OK. If you want to use the default compiler scheme, you may skip this step.
    3. Choose Product > Archive from the main Xcode menu.
    4. Wait for Xcode to work. The Organizer will open when it is finished, displaying the Archives tab. This screen allows you to review, manage, and use archived copies of your applications. You can also add free-form comments to each archive—a very handy feature—and a status line lets you track when archives have been successfully submitted to the App Store.
    5. For ad hoc distribution, click Share. Choose iOS App Store Package (.ipa) as your destination.
    6. Choose your ad hoc provision from the Identity pop-up and click Next.
    7. Specify the name of your new package (for example, HelloApp) and where to save it. Click Save.

    After following these steps, you can now e-mail the newly built .ipa file to members of your beta list or post it to a central site for download.

    The .ipa bundle you built is actually a renamed ZIP file. If you extract it and look inside the Payload folder, you’ll discover the compiled application bundle. This contains an embedded mobile provision that enumerates all the device IDs included in the ad hoc provisioning.

    <string>Wildcard Ad Hoc </string> <key>ProvisionedDevices</key>

    Note - TestFlight offers over-the-air ad hoc management that has become quite popular in the developer community. Visit testflightapp.com for details.

    Over-the-Air Ad Hoc Distribution

    You can distribute Ad Hoc ipa files over the air by creating links to a simple webpage. The itms-services: URL scheme, when pointing to an application manifest property list allows your users to install apps wirelessly. You provide the ipa and the manifest on the website. Here’s how you might link to the manifest.

    <a href="itms-services://?action=download-manifest&\     url=http://example.com/manifest.plist">Install App</a>

    Make sure your website is configured to support the following two MIME types.

    application/octet-stream ipa text/xml plist

    Building a Manifest

    The manifest is an XML-based property list. It must contain six key/value pairs:

    • URL—a fully-qualified URL pointing to the ipa file
    • display-image—a fully-qualified URL pointing to a 57x57-pixel PNG icon used during download and installation
    • full-size-image—a fully-qualified URL pointing to a 512x512-pixel PNG (not JPEG!) image that represents the iTunes app
    • bundle-identifier—the app’s standard application identifier string, as specified in the app’s Info.plist file
    • bundle-version—the app’s current bundle version string, as specified in the app’s Info.plist file
    • title—a human-readable application name

    In addition to these required keys, you can specify an optional md5 hash for file elements. Listing 3-3 shows a sample manifest provided by Apple.

    Listing 3-3  Apple Sample Manifest

    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>
        <!--<span class="code-comment"> array of downloads. --></span>
        <key>items</key>
        <array>
            <dict>
                <!--<span class="code-comment"> an array of assets to download --></span>
                <key>assets</key>
                <array>
                    <!--<span class="code-comment"> software-package: the ipa to install. --></span>
                    <dict>
                        <!--<span class="code-comment"> required.  the asset kind. --></span>
                        <key>kind</key>
                        <string>software-package</string>
                        <!--<span class="code-comment"> optional.  md5 every n bytes.  --></span>
                        <!--<span class="code-comment"> will restart a chunk if md5 fails. --></span>
                        <key>md5-size</key>
                        <integer>10485760</integer>
                        <!--<span class="code-comment"> optional.  array of md5 hashes --></span>
                        <key>md5s</key>
                        <array>
                            <string>41fa64bb7a7cae5a46bfb45821ac8bba</string>
                            <string>51fa64bb7a7cae5a46bfb45821ac8bba</string>
                        </array>
                        <!--<span class="code-comment"> required.  the URL of the file to download. --></span>
                        <key>url</key>
                        <string>http://www.example.com/apps/foo.ipa</string>
                    </dict>
                    <!--<span class="code-comment"> display-image: the icon to display during download .--></span>
                    <dict>
                        <key>kind</key>
                        <string>display-image</string>
                        <!--<span class="code-comment"> optional. icon needs shine effect applied. --></span>
                        <key>needs-shine</key>
                        <true/>
                        <key>url</key>
                        <string>http://www.example.com/image.57x57.png</string>
                    </dict>
                    <!--<span class="code-comment"> full-size-image: the large 512x512 icon used by iTunes. --></span>
                    <dict>
                        <key>kind</key>
                        <string>full-size-image</string>
                        <!--<span class="code-comment"> optional.  one md5 hash for the entire file. --></span>
                        <key>md5</key>
                        <string>61fa64bb7a7cae5a46bfb45821ac8bba</string>
                        <key>needs-shine</key>
                        <true/>
                        <key>url</key>
                        <string>http://www.example.com/image.512x512.jpg</string>
                    </dict>
                </array><key>metadata</key>
                <dict>
                    <!--<span class="code-comment"> required --></span>
                    <key>bundle-identifier</key>
                    <string>com.example.fooapp</string>
                    <!--<span class="code-comment"> optional (software only) --></span>
                    <key>bundle-version</key>
                    <string>1.0</string>
                    <!--<span class="code-comment"> required.  the download kind. --></span>
                    <key>kind</key>
                    <string>software</string>
                    <!--<span class="code-comment"> optional. displayed during download; --></span>
                    <!--<span class="code-comment"> typically company name --></span>
                    <key>subtitle</key>
                     <string>Apple</string>
                     <!--<span class="code-comment"> required.  the title to display during the download. --></span>
                     <key>title</key>
                     <string>Example Corporate App</string>
                 </dict>
             </dict>
         </array>
      </dict> 
    </plist>

    Submitting to the App Store

    To build your application in compliance with the App Store’s submission policies, it must be signed by a valid distribution provision profile using an active developer identity. The steps are very close to those you used to create an ad hoc distribution, but you have additional bookkeeping that you must perform.

    Make sure you have at least one 512·512 PNG image on hand as well as at least one screenshot for the next few steps. If you’re still not ready with final art, you can upload placeholders and replace or delete them later as needed.

    Start by visiting the iOS portal and register your application identifier in the App IDs tab of the portal. This takes just a second or two and requires a common name (for example, “Collage”) and the identifier (for example, com.sadun.Collage). This identifier should exactly match the one you use in Xcode. Even though you usually sign your app with a general wildcard provision, the application identifier you need for iTunes must be specific.

    Head over to iTunes Connect (iTunesConnect.apple.com). Choose Manage Your Applications > Add New App > iOS App. Enter the application name (it must be unique), the SKU number (it’s up to you how you define this, but it must be unique to your account), and select your new identifier from the Bundle ID pop-up. Be exact as possible on this screen and do not use placeholders during this step. Make very sure you select the proper identifier. Once set, it cannot be changed.

    Enter all your metadata—it can all be placeholders here—and set your two images. iTunes Connect creates your new application page and adds a “Ready to Upload Binary” button. When you click that button and declare your export encryption compliance, you’re given instructions on how to upload your binary. Your application state changes from Ready to Upload to Waiting for Upload. Click Continue.

    When you use placeholders in your iPhone metadata, you now have as much time as you need to edit that material. Just be sure you get your descriptions and art into shape before uploading your application from Xcode. Your upload kicks off the App Store review process. Do not waste Apple’s app reviewers’ time by uploading your app until it’s ready to be reviewed.

    Finally, make sure you read Apple’s App Store submission guide, which walks you through the process and its guidelines, which help explain what apps are and are not suitable for the App Store.

    Over-the-Air Ad Hoc Distribution

    You can distribute Ad Hoc ipa files over the air by creating links to a simple webpage. The itms-services: URL scheme, when pointing to an application manifest property list allows your users to install apps wirelessly. You provide the ipa and the manifest on the website. Here’s how you might link to the manifest.

    <a href="itms-services://?action=download-manifest&\     url=http://example.com/manifest.plist">Install App</a>

    Make sure your website is configured to support the following two MIME types.

    application/octet-stream ipa text/xml plist

    Building a Manifest

    The manifest is an XML-based property list. It must contain six key/value pairs:

    • URL—a fully-qualified URL pointing to the ipa file
    • display-image—a fully-qualified URL pointing to a 57x57-pixel PNG icon used during download and installation
    • full-size-image—a fully-qualified URL pointing to a 512x512-pixel PNG (not JPEG!) image that represents the iTunes app
    • bundle-identifier—the app’s standard application identifier string, as specified in the app’s Info.plist file
    • bundle-version—the app’s current bundle version string, as specified in the app’s Info.plist file
    • title—a human-readable application name

    In addition to these required keys, you can specify an optional md5 hash for file elements. Listing 3-3 shows a sample manifest provided by Apple.

    Listing 3-3  Apple Sample Manifest

    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     <plist version="1.0"> <dict>
         <!--<span class="code-comment"> array of downloads. --></span>
         <key>items</key>
         <array>
             <dict>
                 <!--<span class="code-comment"> an array of assets to download --></span>
                 <key>assets</key>
                 <array>
                     <!--<span class="code-comment"> software-package: the ipa to install. --></span>
                     <dict>
                         <!--<span class="code-comment"> required.  the asset kind. --></span>
                         <key>kind</key>
                         <string>software-package</string>
                         <!--<span class="code-comment"> optional.  md5 every n bytes.  --></span>
                         <!--<span class="code-comment"> will restart a chunk if md5 fails. --></span>
                         <key>md5-size</key>
                         <integer>10485760</integer>
                         <!--<span class="code-comment"> optional.  array of md5 hashes --></span>
                         <key>md5s</key>
                         <array>
                             <string>41fa64bb7a7cae5a46bfb45821ac8bba</string>
                             <string>51fa64bb7a7cae5a46bfb45821ac8bba</string>
                         </array>
                         <!--<span class="code-comment"> required.  the URL of the file to download. --></span>
                         <key>url</key>
                         <string>http://www.example.com/apps/foo.ipa</string>
                     </dict>
                     <!--<span class="code-comment"> display-image: the icon to display during download .--></span>
                     <dict>
                         <key>kind</key>
                         <string>display-image</string>
                         <!--<span class="code-comment"> optional. icon needs shine effect applied. --></span>
                         <key>needs-shine</key>
                         <true/>
                         <key>url</key>
                         <string>http://www.example.com/image.57x57.png</string>
                     </dict>
                     <!--<span class="code-comment"> full-size-image: the large 512x512 icon used by iTunes. --></span>
                     <dict>
                         <key>kind</key>
                         <string>full-size-image</string>
                         <!--<span class="code-comment"> optional.  one md5 hash for the entire file. --></span>
                         <key>md5</key>
                         <string>61fa64bb7a7cae5a46bfb45821ac8bba</string>
                         <key>needs-shine</key>
                         <true/>
                         <key>url</key>
                         <string>http://www.example.com/image.512x512.jpg</string>
                     </dict>
                 </array><key>metadata</key>
                 <dict>
                     <!--<span class="code-comment"> required --></span>
                     <key>bundle-identifier</key>
                     <string>com.example.fooapp</string>
                     <!--<span class="code-comment"> optional (software only) --></span>
                     <key>bundle-version</key>
                     <string>1.0</string>
                     <!--<span class="code-comment"> required.  the download kind. --></span>
                     <key>kind</key>
                     <string>software</string>
                     <!--<span class="code-comment"> optional. displayed during download; --></span>
                     <!--<span class="code-comment"> typically company name --></span>
                     <key>subtitle</key>
                     <string>Apple</string>
                     <!--<span class="code-comment"> required.  the title to display during the download. --></span>
                     <key>title</key>
                     <string>Example Corporate App</string>
                 </dict>
             </dict>
         </array>
      </dict> 
     </plist>

    Submitting to the App Store

    To build your application in compliance with the App Store’s submission policies, it must be signed by a valid distribution provision profile using an active developer identity. The steps are very close to those you used to create an ad hoc distribution, but you have additional bookkeeping that you must perform.

    Make sure you have at least one 512·512 PNG image on hand as well as at least one screenshot for the next few steps. If you’re still not ready with final art, you can upload placeholders and replace or delete them later as needed.

    Start by visiting the iOS portal and register your application identifier in the App IDs tab of the portal. This takes just a second or two and requires a common name (for example, “Collage”) and the identifier (for example, com.sadun.Collage). This identifier should exactly match the one you use in Xcode. Even though you usually sign your app with a general wildcard provision, the application identifier you need for iTunes must be specific.

    Head over to iTunes Connect (iTunesConnect.apple.com). Choose Manage Your Applications > Add New App > iOS App. Enter the application name (it must be unique), the SKU number (it’s up to you how you define this, but it must be unique to your account), and select your new identifier from the Bundle ID pop-up. Be exact as possible on this screen and do not use placeholders during this step. Make very sure you select the proper identifier. Once set, it cannot be changed.

    Enter all your metadata—it can all be placeholders here—and set your two images. iTunes Connect creates your new application page and adds a “Ready to Upload Binary” button. When you click that button and declare your export encryption compliance, you’re given instructions on how to upload your binary. Your application state changes from Ready to Upload to Waiting for Upload. Click Continue.

    When you use placeholders in your iPhone metadata, you now have as much time as you need to edit that material. Just be sure you get your descriptions and art into shape before uploading your application from Xcode. Your upload kicks off the App Store review process. Do not waste Apple’s app reviewers’ time by uploading your app until it’s ready to be reviewed.

    Finally, make sure you read Apple’s App Store submission guide, which walks you through the process and its guidelines, which help explain what apps are and are not suitable for the App Store.

    Note - Take special note of the Review Notes area in the Application Metadata. This is your single line of human communication with Apple reviewers. Use this section to explain any areas of confusion you think the reviewer may encounter. Offer how-to procedures if needed and sample account credentials for testing your application.

    When you are absolutely sure you’re ready to submit your application, follow these steps:

    1. Review your iTunes Connect metadata for clarity and correctness.
    2. Archive your application (Product > Archive).
    3. In the Organizer, click Submit.
    4. Enter your developer login credentials and click Next.
    5. Select your application from the top pop-up (see Figure 3-28). Only applications that are “Waiting for Upload” appear in this list.
    6. Select your distribution identity from bottom pop-up. Make sure it is your general distribution identity and not an ad hoc distribution one! This is a common mistake that usually results in an e-mail from iTunes asking you to re-submit your application after it fails the code-signing check. Click Next.
    7. Wait as Xcode validates and submits your application. When it is finished, the Status field next to your application name updates to match the status of your submission. Wait for an e-mail from iTunes saying that your application has changed state to Waiting for Review.
    Figure 3-28
    Only apps that are “Waiting for Upload” are listed in the Organizer’s submission screen. Make sure your identity is not set to an ad hoc profile, also listed as iPhone Distribution. It’s a common error that lots of developers make.

    If you encounter any trouble uploading, you may want to clean your project and recompile from scratch. If you are unable to verify or submit your application, try re-installing Xcode. Sometimes when you install beta versions of the SDK on the same machine as your primary development Xcode SDK, those versions can overwrite the tools you need to properly submit your applications to iTunes Connect.

    Note - Keep on top of your calendar. You must renew your developer membership yearly. Your certificates all have expiration dates as well. When renewing your developer and distribution certificates, you must reissue all your mobile provisions. Throw away the old ones and create new ones with your updated developer identity. Make sure to remove the outdated certificates from your keychain when replacing them with the new ones.

    Summary

    This chapter covered a lot of ground. From start to finish, you saw how to create, compile, and debug Xcode projects. You were introduced to most of the major Xcode components you’ll use on a day-to-day basis, and you read about many of the different ways you can produce and run iPhone projects. Here are some thoughts to take away from this chapter:

    • Although Xcode provides easy-to-use templates, think of them as a jumping-off point, not an endpoint. You can customize and edit projects however you want.
    • Interface Builder makes it really easy to lay out views. Although, technically, you’re producing the same method calls and property assignments as if you’d designed by hand, IB’s elegant GUI transforms those design tasks into the visual domain, which is a welcome place for many developers.
    • Learning to navigate through Xcode’s in-program reference documentation is an essential part of becoming an iPhone developer. No one can keep all that information in his or her head. The more you master the documentation interface, the better you’ll be at finding the class, method, or property you need to move forward.
    • Everything changes. Subscribe to iOS documentation in Xcode and ensure that your documentation remains as up to date as possible.
    • Xcode’s built-in debugger and Instruments tools help you fix bugs faster than trying to figure out everything by hand. The tools may seem complex at first but are well worth mastering for day-to-day development.
    • Get to know and love the Organizer pane. It gives you critical feedback for knowing which devices are connected and what state they are in. And the other tools—including project archives with submission to the App Store, the documentation interface, and the screenshot utility—just add to its power.
    • Xcode 4’s massive update has more power and capabilities than this brief introduction can cover. Other features are discussed in Chapter 4, “Designing Interfaces,” which provides a more detailed overview of Interface Builder.

    © Copyright Pearson Education. All rights reserved.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    About the Author

    Addison-Wesley

    United States United States
    No Biography provided

    Comments and Discussions

     
    -- There are no messages in this forum --
    | Advertise | Privacy | Mobile
    Web02 | 2.8.140721.1 | Last Updated 8 Dec 2011
    Article Copyright 2011 by Addison-Wesley
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid