O'Reilly    
 Published on O'Reilly (http://oreilly.com/)
 See this if you're having trouble printing code examples


Getting Started with the iPhone SDK: Chapter 1 - iPhone SDK Application Development

by Jonathan Zdziarski

If you’re new to the Macintosh world, you might be surprised to find that applications don’t come in the form of .exe files. The excellent design for which Apple is known in its hardware and graphics extends to its software architecture as well, and includes the way applications are laid out in the file system. The same strategy used in Apple desktop systems has been carried over into the iPhone.

iPhone SDK Application Development book cover

This excerpt is from iPhone SDK Application Development. iPhone SDK Application Development introduces you to this development paradigm and the Objective-C language it uses with numerous examples, and also walks you through the many SDK frameworks necessary for designing full-featured applications. The book will benefit experienced developers and those just starting out on the iPhone.

buy button

Apple has adopted the practice of creating modular, self-contained applications with their own internal file resources. As a result, installing an application is as easy as simply dragging it into your applications folder; deleting it as easy as dragging it into the trash. In this chapter, we’ll look at the structure of iPhone applications. You’ll also get up and running with the iPhone SDK, explore the Apple IDE known as Xcode, and learn how to install applications on your iPhone. Finally, we’ll introduce you to the Objective-C language and enough of its idiosyncrasies to make an easy transition from C or C++.

Anatomy of an Application

Apple came up with an elegant way to contain applications in their operating system. As OS X is a Unix-based platform, Apple wanted to make it adhere to basic Unix file conventions, and so the resource forks of olde were no longer sufficient (or efficient, for that matter). The challenge was to design a structure that would allow an application to remain self-contained while surviving on a file system that didn’t believe in cheapening its architecture with proprietary workarounds. The answer came from an older ancestor of Mac OS X named NeXT, which treated an application as a bundle represented within a directory. The bundle concept introduces an approach to group application resources, binaries, and other related files.

If you look at any Mac application, you’ll find that the .app extension denotes not a file, but a directory. This is the application’s program directory. Inside it is an organized structure containing resources the application needs to run, property lists containing information about the application, and the application’s executable binaries. The iPhone SDK builds the binary executable for your program and deposits files it needs into this program directory structure. So to build a complete application, it’s up to the developer to tell the Xcode IDE which supporting files should be installed. Applications are executed from within a sandbox on the iPhone. A sandbox is a restricted environment that prevents applications from accessing unauthorized resources. One of its functions is to prohibit any read or write operations outside of the application’s designated home directory. Everything your application needs to run must be self-contained within this directory structure. In addition to this, your application won’t know where it is installed, as a unique identifier is added to your application’s path at each installation. You’ll only be able to find your path by using functions like NSHomeDirectory and classes like NSBundle, which you’ll learn about in the coming chapters.

Each iPhone application has its own home directory containing Library and Documents folders, and a tmp directory for storing temporary files. The program directory for an iPhone application is much less structured than desktop Mac applications, and all of the application’s resources are stored in the root of the .app program folder. The following is an example of a single application’s complete home directory, as it might appear on the iPhone’s file system:

drwxr-xr-x    mobile  mobile   Documents/
drwxr-xr-x    mobile  mobile   Library/
drwxr-xr-x        mobile  mobile    Preferences/
drwxr-xr-x    mobile  mobile   MyApp.app/
    drw-r--r--    mobile  mobile    _CodeSignature
    -rw-r--r--    mobile  mobile    Default.png
    -rw-r--r--    mobile  mobile    icon.png
    -rw-r--r--    mobile  mobile    Info.plist
    -rwxr-xr-x    mobile  mobile    MyApp
    -rw-r--r--    mobile  mobile    pie.png
    -rw-r--r--    mobile  mobile    PkgInfo
    -rw-r--r--    mobile  mobile    ResourceRules.plist
drwxr-xr-x    mobile  mobile   tmp/

This list reflects a very basic simple iPhone application named MyApp:

Documents

A special folder in which your application may store documents created by the user. It will not be shared with any other applications’ documents.

Library

A folder in which your application may store settings and other resources created after installation. Inside this folder is another folder named Preferences, which will store your application’s preferences. You’ll learn how to access them in Chapter 11, Application Settings.

MyApp.app

The application folder, this represents the actual application. This directory will contain your executable binary and all supporting resources your application relies on.

_CodeSignature

A directory containing code signatures for each file bundled with your application. These ensure that the application has not been modified from its original form. All applications must be signed in order to run on the iPhone.

Default.png

A PNG (portable network graphics) image file containing the application’s default title screen. When the user runs your application, the iPhone animates it to give the appearance that it’s zooming to the front of the screen. The application’s Default.png file is loaded and scaled up until it fills the entire screen. This 320×480 image zooms to the front and remains on the screen until the application finishes launching. Applications generally use a solid black or white background, a logo, or a background resembling the title screen that an application will display after initializing.

icon.png

A PNG image containing the application’s icon. The icon is displayed on the iPhone’s home screen. Apple recommends that icons be 57×57 pixels. This file can be named anything you like, as long as it’s specified in the Info.plist manifest, explained below. Icons are automatically given a “shine” when displayed, so you won’t need to worry about drawing rounded edges or lighting effects on your icon.

Info.plist

A property list containing information about the application. This includes the name of its binary executable and a bundle identifier, which is read when the application is launched. You’ll see an example property list later in this chapter.

MyApp

The actual binary executable that is called when the application is launched. This is what Xcode outputs when it builds your application. Xcode will automatically place the binary in the application folder when performing a Build and Go.

pie.png

An example image resource used by this sample application. The iPhone framework provides many methods to fetch resources, so you don’t need to access them directly by path. This is consistent with Apple’s effort to keep applications self-contained. The Xcode IDE will take any files you’ve dragged into your project’s Resources folder (on the desktop) and will place them into the application’s program folder (on the iPhone) when the project is installed.

PkgInfo

This file contains the eight-byte filetype descriptor for the application. The first four bytes should read APPL, followed by the bundle signature identifier. This is explained in the next section.

Underneath Xcode

Before delving into the many great benefits provided to you by Xcode, it would be healthy to understand the basics of how an application is assembled. In the old world of iPhone hacking, this meant rolling your own application by hand. In Xcode, this is done for you. Here’s what’s going on behind the scenes.

If you were building an application by hand, you’d put together a skeleton .app directory to contain it. The skeleton provides all of the information necessary for the iPhone to acknowledge the existence of your application as a bundle so it can be run from the iPhone’s home screen.

This book presents many fully functional code examples whose skeleton is built automatically by Xcode. After compiling the example, Xcode creates the example’s directory structure inside the project’s build directory and places its binary and resources into the application folder. If you were doing this by hand, creating the directory would be easy enough:

$ mkdir MyExample.app

Next, Xcode copies a property list into the application folder to describe the application and how to launch it. The Info.plist file expresses this information in XML format and looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com
/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleDisplayName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundleExecutable</key>
        <string>${EXECUTABLE_NAME}</string>
        <key>CFBundleIconFile</key>
        <string>icon.png</string>
        <key>CFBundleIdentifier</key>
        <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleResourceSpecification</key>
        <string>ResourceRules.plist</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
        <string>1.0</string>
        <key>LSRequiresIPhoneOS</key>
        <true/>
</dict>
</plist>

The most important keys are CFBundleDisplayName, CFBundleExecutable, CFBundleIconFile, CFBundleIdentifier, and CFBundleName. The CFBundleExecutable property is of particular importance, as it specifies the filename of the binary executable within the folder. This is the file that is executed when your application is launched—the output from your compiler. Xcode normally sets this automatically, but you can override this behavior.

The iPhone’s home screen runs as an application, called Springboard, which is similar to the Finder on a Mac desktop. The Springboard application, as well as much of the iPhone’s application layer, likes to refer to applications using a special identifier instead of its display name; for example com.yourcompany.tictactoe. The value assigned to the CFBundleIdentifier key specifies the unique identifier you’d like to give to your application. Whenever your application is launched, it will be referenced using this identifier. Because the name must be unique among all other applications on the iPhone, it’s common practice to incorporate the URL of your website.

The application’s icon.png and Default.png files are also copied into the program folder, if they exist. If you leave these out, the iPhone will use the worst-looking images possible to serve as default images for both. Make sure to create and include images with these names when you publish your own applications to make them look professional.

Were this application signed by Xcode, it would be good enough to run. In the next section, you’ll install the iPhone SDK on your desktop, which will perform all of these steps for you when you build an application—and sign the build with your developer key.

You’ll get started compiling example applications as early as Chapter 3, Introduction to UI Kit. In the coming chapters, you’ll build many examples. The examples provided in this book generally do not need any additional resources, however a few will use your Internet connection to download sample images or other files.

Note

You can download the code examples in this book from the book’s online repository at http://www.oreilly.com/catalog/9780596154059.

Installing the iPhone SDK

The iPhone began life as a closed platform. Preceding the release of Apple’s iPhone SDK, the open source community successfully hacked into the device and wrote a home-brew compiler to build applications. Later, Apple hired some of the developers of this open source tool chain to design the iPhone SDK. As a result, the two behave in a similar fashion: as cross-compilers. A cross-compiler is a compiler that builds executables for a different architecture than the one it’s running on. Here, the iPhone SDK compiler runs on a Mac OS X desktop machine, but builds executables for the iPhone’s ARM architecture.

Note

The open source iPhone tool chain can run on many different platforms, including natively right on the iPhone, but is not supported by Apple. You’ll need to use the SDK to design applications suitable for distribution on the AppStore, which means your developers will all needs Macs.

The commands and pathnames provided throughout this book assume that you’ve used the procedures from this chapter to install the iPhone SDK in the recommended way. Apple releases new versions of the SDK periodically, so its setup can sometimes change. Newer versions are available on the Apple Developer Connection website at http://developer.apple.com/iphone.

What You’ll Need

The iPhone SDK requires an Intel-based Mac running Mac OS X Leopard. Each version of the SDK has its own particular operating system version requirements. You’ll need about 3.5GB of disk space for the SDK, along with extra disk space for your projects.

While the following aren’t required, they will certainly make developing iPhone applications easier.

Apple developer key

You use Apple developer keys to sign applications so that you can install them on development iPhones. Apple gives developer keys to those accepted into Apple’s developer program. To sign up, visit the Apple Developer Connection website at http://developer.apple.com/iphone. Apple offers two tracks for developers: a standard track and an enterprise track. The standard track provides a basic developer key, allowing you to install applications on your iPhone from Xcode. As a developer, you’ll be able to submit your applications for distribution in the AppStore. The enterprise track, which is more expensive, is designed for enterprises that will be using applications internally or with selected partners instead of distributing them through the AppStore. This track includes additional provisioning keys for large enterprises.

An iPhone

You will need an iPhone, of course, if you want to test applications on an actual iPhone device, as opposed to using the iPhone simulator platform. This is strongly recommended. The iPhone needs to be running a version of firmware supported by your particular version of the SDK.

The iPhone Simulator

Without an Apple developer key or an iPhone, you’ll have to test your applications using the iPhone simulator. The iPhone simulator is a target platform that you can use to deploy and test iPhone applications on the desktop. The simulator provides an iPhone-like environment with menu options to simulate locks, screen rotations, and other basic iPhone events. It is greatly limited, however, because your desktop machine lacks the necessary hardware to perform certain tasks. Using the simulator, you will get a general “feel” for how your application might function, but you will also miss some important functionality:

  • The Core Location API will not be able to provide your GPS coordinates, but may provide you with sample data or broad location-based information, as available for your network.

  • The accelerometer API will not be available to the application.

  • The simulator is limited to only some gestures, such as pinch, and will not support more than two fingers or indiscriminate multi-touch.

  • The application may not initiate phone calls.

  • The EDGE/3G network will be inaccessible, but network queries will use your Internet connection as available.

  • The camera and microphone APIs may not function. If your application enables these features, it may suffer from a fatal exception.

  • Only certain preloaded iPhone applications will be available. These include Contacts, Safari, Photos, and Settings applications.

  • You won’t be able to see whether any parts of your application might tax the iPhone’s CPU or memory, because your desktop machine will have greater resources to run your application. Slow graphics or other issues might not be noticed until it is tested on an actual iPhone.

Downloading and Installing the iPhone SDK

Download the iPhone SDK from the Apple Developer Connection website at http://developer.apple.com/iphone. You will be required to create an account if you don’t already have one. This is free. The entire distribution runs about 2 GB, so you will want to download it over a high speed Internet connection. The SDK itself comes in the form of a disk image file, which will be placed in your Downloads folder by default.

Double-click the disk image to mount it. You should now see the volume iPhone SDK mounted. This will appear on both the sidebar of your Finder and on the desktop. Open the volume and a window will appear.

Inside this window, you will see a package labeled iPhone SDK. Double-click this package to begin the installation process. After agreeing to the various licensing provisions, you will be presented with the installation screen shown in Figure 1.1, “The iPhone SDK installer”.

Figure 1.1. The iPhone SDK installer

The iPhone SDK installer

Ensure that the iPhone SDK option is checked and click Continue. The installer will then install Xcode and the iPhone SDK into /Developer on your desktop machine.

That’s it! You’ve now installed the SDK for iPhone and are ready to start compiling iPhone applications. We’ll explain how to use it in the next section.

Provisioning an iPhone

If you want to install your applications on the iPhone, you’ll need a developer certificate and a mobile provisioning profile from Apple. You can create these through the iPhone Developer Program portal. You’ll need to pay a fee to join one of the program tracks before you can create a profile. You may sign up by registering at http://developer.apple.com. Once you’ve been accepted into the developer program, you’ll be provided instructions to access the developer’s portal.

To get set up, you’ll perform the following basic steps. Because the program portal’s interface is subject to change, use the following only as a guide and be sure to follow the portal’s online instructions:

  • Log into the program portal. The first thing to do is create a developer certificate. Xcode uses this certificate to sign your applications. Click the Certificates tab and follow the instructions to add a new certificate. Once created, download the certificate and the WWDR Intermediate Certificate as instructed. The WWDR Intermediate Certificate is Apple’s key, which you’ll also need. Once downloaded, double-click each of these certificates to add them to your keychain.

  • Now register your iPhone in the portal by clicking the Devices tab. Registering your iPhone is necessary because you can only install your test applications on registered devices. You’ll need your iPhone’s unique device ID, which you can obtain from Xcode’s device organizer. Launch Xcode, then go to the Windows menu and select Organizer. This will cause a window, shown in Figure 1.2, “Xcode Organizer window”, to appear with a list of devices. Connect your iPhone, and you will be prompted to use the device for development. Click the device in the left pane of the organizer. An information window will appear containing the device ID of the iPhone. Use this to register your iPhone in the program portal.

  • Next, click the App IDs tab to create an application bundle identifier. This identifies the application (or group of applications) you’ll be developing. This identifier can be wildcarded, allowing you to install any application using a given bundle prefix. To run this book’s examples on your iPhone, create a wildcard using com.yourcompany.* as a bundle identifier. You can name the application “Examples,” or whatever you like.

  • Next, create a provisioning profile for your mobile device. The provisioning profile allows you to install applications compiled with the identifier you’ve just created on your iPhone. Select the application ID to associate with the profile, as well as the developer certificates and devices to use with the profile. After you’ve created the profile, download it to your desktop.

  • To add the provisioning profile to your iPhone, click the plus sign (+) in the organizer underneath the box labeled Provisioning and navigate to your provisioning certificate. Once installed, you’ll be able to install applications onto this device from Xcode.

Note

The organizer window also allows you to view the console and crash logs from your device, and take screenshots.

Figure 1.2. Xcode Organizer window

Xcode Organizer window

Building and Installing Applications

Now that you’ve installed the iPhone SDK, the next step is to learn how to use it. The iPhone SDK functions as a component of the Xcode IDE. To launch Xcode, navigate to the newly created /Developer directory on your hard drive. Open a finder window and then click the disk icon in the sidebar. Now double-click the Developer folder, followed by Applications. Drag the Xcode application onto your dock to make launching it easier.

Note

The /Developer/Applications folder is separate from Mac OS’s default Applications folder. You can drag the folder onto the dock as a stack to have all developer applications easily accessible, or drag it onto the sidebar to click through to it using the Finder. You’ll be accessing this folder a lot as you continue to develop software, so you’ll want to make it easy to get to.

After launching Xcode, select New Project from the File menu. A window will appear, prompting you to select a template for your new project. Underneath the iPhone OS heading, click the Application category. You’ll see several different types of application templates to choose from, as shown in Figure 1.3, “Available iPhone application templates”.

Figure 1.3. Available iPhone application templates

Available iPhone application templates

Model-View-Controller

Software development on the iPhone follows the model-view-controller (MVC) paradigm. The goal of this architecture is to abstract business logic, such as your application’s data and the rules that govern it, from the user interface (UI) components displayed to the end user. Three key pieces are needed to implement MVC. The model represents the data and business logic for your application. The view represents the UI elements that present the data to the user and allow them to act on it. The controller provides the interaction between the UI elements and the data, such as responding to multi-touch gestures, interaction events, and transitioning between different portions of the logic.

You’ll see these concepts reflected in the names given to many iPhone classes. In many cases, controllers will also encapsulate a view, making it easy to control the view without having to write very much code to connect them.

Application Templates

Xcode provides several skeletons for implementing the MVC architecture in your application. The following templates are most commonly used:

View-based application

Applications using only one view should use this template. A simple view controller manages the application’s primary view, using an interface-builder template for layout (although we’ll show you how to remove this and build your own if you like). Simple applications without any navigation should use this template. If your application requires navigation through multiple views, consider using the navigation-based template.

Navigation-based application

The navigation-based template is ideal for applications that traverse multiple views and require a means of navigation between them. If you can envision your application having screens with “Back” buttons in them, chances are you should use this template. A navigation controller handles all of the internal work in setting up navigation buttons and transitioning between “stacks” of views. This template provides a basic navigation controller and a root (base-tier) view controller to display information.

Utility application

Ideal for widget-type applications, where an application has a main view that you can “flip” around like a widget in Leopard. You may also be familiar with these from Konfabulator (the third-party predecessor to Apple’s Dashboard). The iPhone’s Weather and Stocks applications are good examples of utility applications. This template also includes an information button that causes the view to flip around to display the application’s flipside, which is commonly used to change settings or the information displayed.

OpenGL ES application

If you’re creating 3D games or graphics, use this template. It creates a view configured to render a GL scene and provides a sample timer to animate it. OpenGL programming is not covered in this book.

Tab bar application

Provides a special controller displaying a button bar along the bottom of the screen. This template is ideal for applications such as the iPod or Mobile Phone applications, where a row of tabs along the bottom provides a series of shortcuts to the core functionality of the application.

Window-based application

If none of the other five templates suits your needs, this very basic template provides a simple application with a window. This is the bare minimum framework you’ll need in order to start your own application.

Xcode Project Layout

After creating a new project, its contents will be laid out in a self-contained window like Figure 1.4, “A newly created iPhone project”. The project encapsulates the sources, frameworks, and resources for the application.

Figure 1.4. A newly created iPhone project

A newly created iPhone project

The following groups can help organize your project:

Classes

The files containing the Objective-C classes that your applications use. These include the application delegate object, view controllers, and other objects you create. As you add new class files to your application, they will appear in this group.

Other sources

Other sources compiled into your application. By default, this includes precompiled headers and your application’s main function, which instantiates the Cocoa application object. If your application incorporates additional C functions or C++ classes, add the files here.

Resources

Application resources that are not compiled in with your application’s source code, but are copied into the program folder when the application is built. These can include images or sounds, game levels, or other important files.

Frameworks

The frameworks that your application links with. These are shared libraries linked at build time to add functionality. For example, a 3D game will link with the OpenGLES framework, which contains the routines to render 3G graphics. Sound-intensive applications will likely take advantage of the Audio Toolbox or AVFoundation frameworks, which contain routines for playing and mixing different types of sound.

Products

The build target for your application.

Prototypes

Throughout this book, you’ll be given a list of prototypes to check out at the end of most sections. Prototypes are header files that contain a list of all supported methods and properties that are available to you as a developer. While this book covers a majority of the methods and properties available, reading the prototypes on your own might reveal additional, and sometimes obscure interfaces that may have either gone undocumented or been added since this book’s release. They’ll also show you what arguments a method expects, and what data types will be returned.

You can find header files within a framework folder’s Headers subfolder. Because there are different versions of the SDK, the exact path these can be found differs slightly. The standard format for the path to these prototypes is:

/Developer/Platforms/PLATFORM/Developer/SDKs/VERSION/System/Library/Frameworks/

The full path relies on two variables, PLATFORM and VERSION. There are two primary platforms in the SDK: iPhoneOS.platform and iPhoneSimulator.platform. You use the former when building an application for an iPhone or iPod Touch device, and the simulator platform when you build an application for the iPhone simulator. Each platform contains its own set of frameworks, shared libraries, and prototypes.

The VERSION variable refers to the version of the iPhone SDK for that platform. The version is prefixed by the platform name and suffixed with an .sdk extension.

The full path for an iPhone platform running the version 2.2 SDK would look like the example below:

/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/System/Library/Frameworks/

To make it easy to find this directory, add the following to your .profile script, so that the SDK environment variable is set every time a new shell is created:

export PLATFORM=iPhoneOS
export VERSION=2.2
export SDK=/Developer/Platforms/${PLATFORM}.platform/Developer/SDKs\
/${PLATFORM}${VERSION}.sdk/System/Library/Frameworks

You’ll then be able to change directory using the environment variable SDK:

$ cd ${SDK}

Within the folder at this path, you will find the individual frameworks available in the SDK, each with a Headers directory containing the prototypes for that framework. Be sure to check these out when prompted, as they contain a great wealth of verbose information about what’s available to developers. The general rule of thumb is this: if you find a class, property, or method in the SDK headers, it should be sanctioned for use in your application.

Note

While a framework’s headers will tell you which APIs you can use, they will not necessarily tell you in what way they can be used. Apple maintains a set of human interface guidelines and other policies that govern AppStore software. You’ll need to be sure your application doesn’t violate any of Apple’s nontechnical restrictions, such as duplicating functionality of an existing preloaded application. Consult the latest version of your SDK agreement and other supporting documents from Apple to learn about design restrictions.

Adding Frameworks

For a given type of functionality, all of the classes and methods needed to provide it are grouped into a framework. For example, the Core Location framework provides all of the functionality needed to perform global positioning. The UI Kit framework provides all of the functionality needed to implement user interfaces. You’ll need to link to a framework in order to use the functionality it provides. This design logically separates the different pieces of the iPhone’s operating system for developers, and allows your application to link only to the components it needs.

Note

When you link a framework with your application, its classes, functions, and symbols are made available to your application as if you wrote them yourself. Static linking compiles the objects directly into your application. Dynamic linking loads the objects at runtime. Adding a framework in the following fashion uses the dynamic method of linking.

Throughout this book, you may be prompted to add one or two frameworks to your example in order to add support for a particular type of functionality. To do this, Right-click the Frameworks folder in your Xcode project and select Add→Existing Frameworks, as shown in Figure 1.5, “Adding an existing framework in Xcode”. Navigate to the iPhone SDK’s Frameworks directory and choose the correct framework folder. Upon clicking the Add button, you should see the new framework appear in the Frameworks folder of your project. This will link the framework with your application.

Note

It may be necessary to navigate to the Frameworks folder within your SDK. Use the pathnames you’ve just learned about for prototypes to find them.

Figure 1.5. Adding an existing framework in Xcode

Adding an existing framework in Xcode

Setting the Active SDK

Xcode allows you to build your application for either a physical iPhone device or for the integrated iPhone simulator. Different versions of the SDK may also be used to accommodate a specific version of the iPhone firmware. To switch between device and simulator builds, or to change the SDK version, click the Project menu in Xcode. Scroll down to the menu item labeled Set Active SDK and choose the SDK you want to build for. You can also choose whether to build with or without debugging support by choosing from the menu labeled Set Active Build Configuration. Building for the Debug configuration will allow you to trace your application’s program execution to identify potential problems.

Building an Application

There are two ways to build an application using Xcode: the GUI and the command line. The easiest way, of course, is to simply click the Build button at the top of the project window or to click Build and Go to build and run the application. This will invoke the compiler and output the results of the build into the status bar. If the build fails or has warnings, you’ll be able to click the appropriate icons on the status bar to get more information.

If you come from a Unix background, or just have an affinity for pain, you may be more comfortable building on the command line, especially if you use a command-line text editor in lieu of the Xcode IDE. To build from the command line, use the xcodebuild command:

$ xcodebuild -target Project_Name

Installing an Application

Once you have built an application, you can install it on your iPhone directly through Xcode. As mentioned earlier, this requires a valid developer key from Apple. When the application is installed, it will immediately appear on the iPhone’s home screen, then be launched by the debugger.

To install from within Xcode, use the Build and Go toolbar button. This will recompile any changes made since the last build and install it onto the iPhone. If you don’t have a developer key, and are building for the iPhone simulator platform, the application will be installed in the iPhone simulator and then run.

To install from the command line, use the xcodebuild command with the install build option:

$ xcodebuild install -target Project_Name

Transitioning to Objective-C

Objective-C was written by scientist and software engineer Brad Cox in the early 1980s. It was designed as a way of introducing the capabilities of the Smalltalk language into a C programming environment. A majority of the iPhone’s framework libraries are written in Objective-C, but because the language was designed to accommodate the C language, you can use both C and C++ in your application as well. Objective-C is used primarily on Mac OS X and GNUstep (a free OpenStep environment). Many languages, such as Java and C#, have borrowed from the Objective-C language. The Cocoa framework makes heavy use of Objective-C on the Mac desktop, which also carried over onto the iPhone.

If you’ve developed on the Mac OS X desktop before, you’re already familiar with Objective-C, but if the iPhone is your first Apple platform, you may be transitioning from C, C++, or another similar language. This section will cover some of the more significant differences between these languages. If you have a prior background in C or C++, this should be enough to get you up and writing code using the examples in this book as a guide.

Messaging

The first thing you’ll notice in Objective-C is the heavy use of brackets. In Objective-C, methods are not called in a traditional sense; their objects are sent messages. Likewise, a method doesn’t return, but rather responds to the message.

Much of this can be chalked up to semantics, however, at least in terms of what the developer experiences. Your application’s program flow is nothing alien to a C or C++ program: when you invoke a method, your program waits for a response before continuing, allowing you to assign the return value or invoke methods as part of conditional statements.

Unlike C, where function calls must be predefined, Objective-C’s messaging style allows the developer to dynamically create new methods and messages at runtime, or test to see whether an object responds to a particular message. The downside to this is that it’s entirely possible to send an object a message to which it isn’t programmed to respond, causing an exception and likely program termination. For example, you can compile code that will send the following message to an object:

[ myObject heyWhatsUpHowYouDoin ];

At runtime, the application will raise an exception unless a method exists named heyWhatsUpHowYouDoin to respond to the message. Of course, the advantage to this is that a method might exist for the object, but be undocumented in the class’s prototypes. We’ll show you just a few examples of undocumented methods like this in Chapter 3, Introduction to UI Kit.

Given an object named myWidget, a message can be sent to its powerOn method this way:

returnValue = [ myWidget powerOn ];

The C++ equivalent of this might look like the following:

returnValue = myWidget->powerOn();

The C equivalent might declare a function inside of its flat namespace:

returnValue = widget_powerOn(myWidget);

Arguments can also be passed with messages, provided that an object can receive them. The following example invokes a method named setSpeed and passes two arguments:

returnValue = [ myWidget setSpeed: 10.0 withMass: 33.0 ];

Notice the second argument is explicitly named in the message. This allows multiple methods with the same name and argument data types to be declared—polymorphism on steroids:

returnValue = [ myWidget setSpeed: 10.0 withMass: 33.0 ];
returnValue = [ myWidget setSpeed: 10.0 withGyroscope: 10.0 ];

Class and Method Declarations

While you can define C++ classes in Objective-C, the whole point of using the language is to take advantage of Objective-C’s own objects and features. This extends to its use of interfaces. In standard C++, classes are structures, and their variables and methods are contained inside the structure. Objective-C, on the other hand, keeps its variables in one part of the class and methods in another. The language also requires that you specifically declare the interface declaration in its own code block (called @interface) separate from the block containing the implementation (called @implementation). You construct and name methods in a Smalltalk-esque fashion, and they somewhat resemble regular C functions.

The interface for our widget example might look like Example 1.1, “Sample interface (MyWidget.h)”, which is a file named MyWidget.h.

Example 1.1. Sample interface (MyWidget.h)

#import <Foundation/Foundation.h>

@interface MyWidget : BaseWidget
{
    BOOL isPoweredOn;
    @private float speed;
    @protected float mass;
    @protected float gyroscope;
}
+ (id)alloc;
+ (BOOL)needsBatteries;
- (BOOL)powerOn;
- (void)setSpeed:(float)_speed;
- (void)setSpeed:(float)_speed withMass:(float)_mass;
- (void)setSpeed:(float)_speed withGyroscope:(float)_gyroscope;
@end

The important semantic elements in this file are explained in the following sections.

The “id” data type

In the example just shown, the id data type is defined as the return type by the alloc method. This data type is a generic type used to reference any arbitrary object. Think of the id data type as the Objective-C version of a void pointer. Wherever specified, any object can be used. You’ll see this data type used throughout the book, especially in cases where a delegate is assigned to an object to receive special notifications of events.

Imports

The preprocessor directive #import replaces the traditional #include directive (although #include may still be used). One advantage to using #import is that it has built-in logic to ensure that the same resource is never included more than once. This replaces the roundabout use of macro flags found routinely in C code:

#ifndef _MYWIDGET_H
#define _MYWIDGET_H
...
#endif

Interface declaration

The interface for a class is declared with the @interface statement followed by the interface’s name and the base class (if any) it is derived from. At the end of your class declaration, you’ll end the block with the @end statement. Within this block, you’ll declare all class variables and methods for the class.

Methods

Methods should be declared outside of the braces structure. A plus sign (+) identifies the method as a static method, while a minus sign (−) declares the method as an instance method. Static methods don’t need to be invoked for any particular object; they are methods that represent the entire class in general—for example, “the Widget class”. Instance methods are invoked for a named instance of a class—for example, “my Widget” and “his Widget”.

The alloc method is a good example of a static method. It is responsible for allocating and returning a new instance of the given class. In your code, you’ll call this method whenever you create a new object by referencing the class directly, for example MyWidget. Instance methods that are specific to an instance of the MyWidget class, such as setSpeed and powerOn, should be invoked by referencing the named object. Many Cocoa classes provide static and instance methods for initializing objects.

Every declared parameter for a method specifies a data type, a local variable name, and an optional external variable name. Examples of external variable names in Example 1.2, “Sample implementation (MyWidget.m)” are withMass and withGyroscope. The notifier (calling method) that invokes the method refers to method’s external (public) variable names, but inside the method the arguments are referenced using their local variable names. Thus, the setSpeed method uses the local _mass variable to retrieve the value passed as withMass.

If no external variable name is supplied in the declaration, the variable is referenced only with a colon, for example :10.0.

Implementation

The suffix for an Objective-C source code file is .m. A skeleton implementation of the widget class from the last section might look like Example 1.2, “Sample implementation (MyWidget.m)”, which is named MyWidget.m.

Example 1.2. Sample implementation (MyWidget.m)

#import "MyWidget.h"

@implementation MyWidget

+ (BOOL)needsBatteries {
    return YES;
}

- (BOOL)powerOn {
    isPoweredOn = YES;
    return YES;
}

- (void)setSpeed:(float)_speed {
    speed = _speed;
}

- (void)setSpeed:(float)_speed withMass:(float)_mass {
    speed = _speed;
    mass = _mass;
}

- (void)setSpeed:(float)_speed withGyroscope:(float)_gyroscope {
    speed = _speed;
    gyroscope = _gyroscope;
}
@end

Just as the interface was contained within a single code block, the implementation begins with an @implementation statement and ends with @end.

In C++, it is common practice to prefix member variables so that public methods can accept the actual name of the variable. This makes it easy to reuse someone else’s code because you can deduce a variable’s purpose by its name. Since Objective-C allows you to use both an internal and external variable name, a method is able to provide a sensible name for the developer to use, while internally using some proprietary name. The true name can then be referenced as a parameter of the method, while the method’s local variable name is prefixed with an underscore; e.g., _speed.

Consider the example setSpeed method just shown. When invoked, its external argument name, withMass, is used:

[ myWidget setSpeed: 1.0 withMass: 2.0 ];

Inside the method’s code block, the internal variable name, _mass, is used:

- (void)setSpeed:(float)_speed withMass:(float)_mass {
    speed = _speed;
    mass = _mass;
}

Properties

Objective-C 2.0 introduced the concept of properties. Properties are an intermediary between instance variables and methods; they add a syntactic convenience by allowing the developer to address variables directly, rather than through separate setter/getter methods. Properties are similar to public variables, but allow the behavior of their access to be defined. Additionally, properties invoke methods that can be overridden when the property is read from or written to.

To work with an instance variable in earlier versions of Objective-C, you would typically write two methods—one to read the variable (a getter) and one to write (a setter):

BOOL myVariable = [ myClass variable ];     /* getter */
[ myClass.setVariable ] = YES;       /* setter */

Properties allow the developer to change his syntax to address the property’s name for both operations. This changes the code to look more “C-ish”:

BOOL myVariable = myClass.variable;
myClass.variable = YES;

You can define properties with a number of different storage semantics. These include assign, retain, and copy. You can also define properties as readonly. Define a property for a variable named size in the class definition as follows:

@interface MyClass : BaseClass
{
    int size;
}
@property(copy) int size;

In the class’s implementation, use the @synthesize statement to implement the property:

@implementation MyClass
@synthesize size;
...
@end

When the @synthesize statement is used, a getter and setter method are automatically generated internally if they don’t exist in your code. These methods are transparently called whenever the property is accessed:

myClass.size = 3;

You can also define custom setter and getter methods without using @synthesize:

-(int)myGetter;
-(void)setSize:(int)size;

@property(copy,getter=myGetter) int size;

Many methods you may have seen in previous versions of Objective-C code have been replaced with properties in the iPhone SDK.

Protocols

A protocol is a set of methods that an object agrees to implement in order to communicate with another object. You’ll use many protocols throughout this book known as delegate protocols. Delegate protocols are protocols that notify an object about events occurring in another object. To implement a protocol, your interface declaration simply declares that it supports the given protocol. This way, other classes requiring a certain protocol can expect that your class will respond to the methods used in the protocol. A class can implement any number of protocols. You’ll receive a compiler warning if your implementation is incomplete.

As an example, presume that a BaseWidgetDelegate protocol is a protocol you’ve designed to alert an object of events occurring within a given widget, such as a powering on event or the event of its power settings changing.

Use the protocol statement to define the methods used in the protocol. You can specify the methods that are mandatory to implement the protocol using the required statement:

@protocol BaseWidgetDelegate

- (void)baseWidgetDidChangePowerSettings:(float)newPowerLevel;

@required
- (void)baseWidgetDidGetTurnedOn:(id)widget; /* This method is required */

@end

A class looking to send these types of notifications might define a variable containing the pointer to an object to receive notifications:

@interface MyWidget : BaseWidget {
    id delegate;
}

They can define a property for its delegate and require that the object assigned to it implement the BaseWidgetDelegate protocol:

@property(assign) id<BaseWidgetDelegate> delegate;

The class desiring to receive notifications must now implement the BaseWidgetDele⁠gate protocol to be assigned as the widget’s delegate. The example to follow declares a WidgetManager class and specifies the protocol be implemented within the class:

@protocol BaseWidgetDelegate;
@interface WidgetManager : NSObject <BaseWidgetDelegate>
...
@end

The only thing remaining is to implement the actual protocol methods in the class’s implementation.

Once implemented, your application code can assign the widget manager class to the widget’s delegate property without generating a compiler warning, because it implements the BaseWidgetDelegate protocol:

myWidget.delegate = myWidgetManager;

Categories

Objective-C adds a new element to object oriented programming called categories. Categories were designed to solve the problem where base classes are treated as fragile to prevent seemingly innocuous changes from breaking the more complex derived classes. When a program grows to a certain size, the developer can often become afraid to touch a smaller base class because it’s too difficult by then to determine which changes are safe without auditing the entire application. Categories provide a mechanism to add functionality to smaller classes without exposing your changes to legacy code.

You can place a category class “on top” of a smaller class, adding to or replacing methods within the base class. This can be done without recompiling or even having access to the base class’ source code. Categories allow you to expand base classes within a limited scope so that any objects using the base class (and not the category) will continue to see the original version. From a development perspective, this makes it much easier to improve on a class written by a different developer. At runtime, portions of code using the category will see the new version of the class, and legacy code using the base class directly will see only the original version.

You might be thinking about inheritance as an equally viable solution. The difference between categories and inheritance is the difference between performance-tuning your car versus dressing it up as a parade float. When you tune up your sports car, you add new components to the internals of the vehicle, which cause it to perform differently. You may even pull out some components and replace them with new ones. The act of adding a new component to the engine, such as a turbo, affects the function of the entire vehicle. This is how inheritance works.

Categories, on the other hand, are more like a parade float in that the vehicle remains completely intact, but cardboard cutouts and papier-mâché are affixed to the outside of the vehicle so that it only appears different. In the context of a parade, the vehicle is a completely different animal to spectators, but when you take it to the mechanic, it’s the same old stock car you’ve been driving around.

As an example, the widget factory is coming out with a new type of widget that can fly through space, but is concerned that making changes to the base class might break existing applications. By building a category, the developers ensure that applications using the MyWidget base class will continue to see the original class, while the newer space applications will use a category instead. The following example builds a new category named MySpaceWidget on top of the existing MyWidget base class. Because we need the ability to blow things up in space, a method named selfDestruct is added. This category also replaces the existing powerOn method with its own. Contrast the use of parentheses here to hold the MySpaceWidget contained class with the use of a colon in Example 1.1, “Sample interface (MyWidget.h)” to carry out inheritance:

#import "MyWidget.h"

@interface MyWidget (MySpaceWidget)
- (void)selfDestruct;
- (BOOL)powerOn;
@end

A complete source file implementing the category is shown in Example 1.3, “Sample category (MySpaceWidget.m)”.

Example 1.3. Sample category (MySpaceWidget.m)

#import "MySpaceWidget.h"

@implementation MyWidget (MySpaceWidget)

- (void)selfDestruct {
    isPoweredOn = 0;
    speed = 1000.0;
    mass = 0;
}

- (BOOL)powerOn {
    if (speed == 0) {
        isPoweredOn = YES;
        return YES;
    }

    /* Don't power on if the spaceship is moving */
    return NO;
}
@end

Posing

In Objective-C, a subclass can pose as one of its super-classes, virtually replacing it as the recipient of all messages. This is similar to overriding; only an entire class is being overridden instead of a single method. A posing class is not permitted to declare any new variables, although it may override or replace existing methods. Posing is similar to categories in that it allows a developer to augment an existing class at runtime.

In past examples, you created some mechanical widget classes. Well, at some point after designing all of these widgets, you developed a need to perform advanced diagnostics. Rather than rip out functions in the original class, you’ve decided to create a new subclass named MyDiagnosticsWidget. See Examples 1.4 and 1.5.

Example 1.4. Sample interface for posing (MyDiagnosticsWidget.h)

#import <Foundation/Foundation.h>
#import "MyWidget.h"

@interface MyDiagnosticsWidget : MyWidget
{

}

- (void)debug;
@end

Example 1.5. Sample implementation for posing (MyDiagnosticsWidget.m)

#import "MyDiagnosticsWidget.h"

@implementation MyDiagnosticsWidget

- (void)debug {
    /* Generate debugging information */
}
@end

Instead of changing all of the existing code to use this class, the autonomous class can simply pose as the widget class. The class_poseAs method is called from the main program or another high-level method to invoke this behavior:

MyDiagnosticsWidget *myDiagWidget = [ MyDiagnosticsWidget alloc ];
    MyWidget *myWidget = [ MyWidget alloc ];
    class_poseAs(myDiagWidget, myWidget);

Now, any other methods you’ve replaced in the posing class would pose as if they were from the original base class.

Additional Resources

As you read many examples in this book, you’ll see references to objects used in Apple’s Cocoa environment. Most of these objects will begin with the prefix NS, such as NSError or NSString. The Cocoa environment provides a number of standard objects like this to handle arrays, strings, and other such objects; many are available both with the iPhone and the Mac OS X desktop environments. We’ll show you how to work with some of these objects in relation to the example at hand, however entire books have been written just to document Cocoa classes. If you run into a class you’re not familiar with, Apple’s online documentation can provide you with a complete explanation. The Apple Developer Connection website hosts a Cocoa reference available at http://developer.apple.com/reference/Cocoa/. From here, you can read a reference for a particular topic or enter the class’s name into the search window to be taken directly to the class’s documentation.

To learn more about Cocoa and Objective-C programming, you may also check out the following great resources from O’Reilly:

Learning Cocoa with Objective-C, Second Edition, by James Duncan Davidson and Apple Computer, Inc.[1]

http://www.oreilly.com/catalog/learncocoa2/

Objective-C Pocket Reference by Andrew M. Duncan

http://www.oreilly.com/catalog/objectcpr/



[1] Learning Cocoa 3.0 with Objective-C, by Greg Winton and Michael Beam, will be available from O’Reilly in the summer of 2009.

If you enjoyed this excerpt, buy a copy of iPhone SDK Application Development.

Copyright © 2009 O'Reilly Media, Inc.