Chapter 10. Learning Objective-C and the iPhone OS

This chapter covers

Over the next several chapters we’re going to dig into the other side of iPhone development, where you’ll be programming native applications using Apple’s own toolkit. As we discussed back in chapter 2, there are a number of reasons that the SDK is better than web development, just as the opposite is the case, depending on your particular needs.

In this chapter, we assume you have a good understanding of a rigorous programming language (like C), that you know the basic concepts behind object-oriented programming (OOP), and that you understand what the MVC architectural model is. If you aren’t familiar with any of these topics, just jump back to the previous chapter, where we give each of these topics an overview.

With that said, we’re now ready to move into the world of SDK development. We’ll download the SDK first thing so that we can see what it consists of, but then we’re going to take a step back to examine the programming language and frameworks that you’ll be using when you program with the SDK.

10.1. Getting ready for the SDK

The iPhone SDK (Software Development Kit) is a suite of programs available in one gargantuan (over 1GB) download from Apple. It’ll give you the tools you need to program (Xcode), debug (Instruments), and test (iPhone Simulator) your iPhone code. Note that you must have an Apple Macintosh running Mac OS X 10.5.3 or higher to use the SDK.

10.1.1. Installing the SDK

To obtain the SDK, download it from Apple’s iPhone Dev Center, which at time of this writing is accessible at http://developer.apple.com/iphone/. You’ll need to register as an iPhone Developer in order to get here, though it’s a fairly painless process. Note that this is also the site you can use to access Apple documents, as we’ve mentioned earlier.


The Apple docs and the SDK

We’ve already highlighted the fact that the Apple Developer Connection (ADC) provides access to numerous programming documents. For your SDK needs, you’ll want to visit http://developer.apple.com/iphone/, which contains a few introductory papers, of which we think the best are “iPhone OS Overview” and “Learning Objective-C: A Primer,” plus the complete class and protocol references for the SDK.

As we’ll discuss in the next chapter, you can also access all of these docs from inside Xcode. We usually find Xcode a better interface because it allows you to click through from your source code to your local documents. Nonetheless, the website is a great source of information when you don’t have Xcode handy.

As with the web chapters of this book, we’ve been constantly aware of Apple’s documents while writing this part of the book, and we’ve done our best to ensure that what we include complements Apple’s information. We’ll continue to provide you with the introductions to the topics and to point you toward the references when there’s need for in-depth information.


Once you’ve downloaded the SDK, you’ll find that it leaves a disk image sitting on your hard drive. You just need to double-click it and then click on iphone SDK in the folder that pops up, as shown in figure 10.1.

Figure 10.1. Clicking iPhone SDK will start your installation.

This will bring you through the entire install process, which will probably take 20–40 minutes. You’ll also get a few licensing agreements that you need to sign off on, including the iPhone Licensing Agreement, which lists some restrictions on what you’ll be able to build for the iPhone.


iPhone SDK licensing restrictions

Although they’re making the iPhone SDK widely available for public programming, Apple has placed some restrictions on what you can do with it. We expect these restrictions will change as the SDK program evolves, but what follows are some of the limitations at the time of this writing.

Among the most notable technical restrictions: you can’t use the code to create plug-ins, nor can you use it to download non-SDK code. It was the latter that apparently spoiled Sun’s original plans to port Java over to the iPhone. You also can use only Apple’s published APIs. In addition, there are numerous privacy-related restrictions, the most important of which is that you can’t log the user’s location without permission. Finally, Apple includes some specific application restrictions. You can’t create a program that does real-time route guidance, you can’t write programs that include pornography or other objectionable content, and you can’t include voice-over IP functionality.

In order for your program to run on iPhones, you’re going to need an Apple certificate, and Apple maintains the right to refuse those certs if they don’t like what you’re doing. So, if you’re planning on writing anything that might be questionable, you should probably check whether Apple is likely to approve it first.


When the SDK finishes installing, you’ll find it in the /Developer area of your disk. Most of the programs appear in /Developer/Applications, which we suggest you make accessible using the Add to Sidebar feature in your Finder. The iPhone Simulator is located separately at /Developer/Platforms/iPhoneSimulator.platform/Developer/ Applications. Since this is off on its own, you might want to add it to your Dock.


Warning: installation dangers

The SDK development tools will replace any existing Apple development tools that you have. You’ll still be able to do regular Apple development, but you’ll now be working with a slightly more bleeding-edge development environment.


You’ve now got everything that you need to program for the iPhone, but you won’t actually be able to release iPhone programs. That takes a special certificate from Apple. See appendix C for complete information on this process, which is critical for moving your iPhone programs from the iPhone Simulator onto a real iPhone. For now, though, we’ll assume that you’re using the iPhone Simulator, and will warn you when you can’t. The iPhone Simulator turns out to be just one of several programs that you installed, each of which can be useful in SDK programming.

10.1.2. The anatomy of the SDK

Xcode, Instruments, and Dashcode were all available as part of the development library of Mac OS X even before the iPhone came along. Many of these programs are expanded and revised for use on the iPhone, so we’ve opted to briefly summarize them all, in decreasing order of importance to an SDK developer:

  • Xcode is the core of the SDK’s integrated development environment. It’s where you’ll set up projects, write code in a text editor, compile code, and generally manage your applications. It supports code written in Objective-C (a superset of C that we’ll cover in more depth shortly) and can also parse C++ code. You’ll learn the specifics of how to use it in chapter 11.
  • Interface Builder is a tool that lets you put together the graphical elements of your program, including windows and menus, via a quick, reliable method. It’s tightly integrated with Xcode, and you’ll always be using it, even when you don’t call up the program. We’ll introduce you to Interface Builder in chapter 12.
  • iPhone Simulator allows you to view an iPhone screen on your desktop. We’ve already seen that it’s a great help for debugging web pages. It’s an even bigger help when working on native apps, because you don’t have to get your code signed by Apple to test it out here.
  • Instruments is a program that allows you to dynamically debug, profile, and trace your program. Whereas we had to point you to a slew of browsers, addons, and remote web sites to do this sort of work for web apps, for your native apps that’s all incorporated into this one package. Space precludes us from talking much about this program.
  • Dashcode we list here only for the sake of completeness since it’s part of the /Developer area. It’s a graphical development environment that is used to create web-based programs incorporating HTML, CSS, and JavaScript. You won’t use it in SDK development, but we described its usefulness for web programmers back in chapter 7.

Figure 10.2 shows off the three most important Developer tools.

Figure 10.2. The SDK includes Xcode (left), Interface Builder (center), and the iPhone Simulator (right).

Besides the visible tools that you’ve downloaded into /Developer, you’ve also downloaded the entire set of iPhone OS frameworks, a huge collection of header files and source code—all written in Objective-C—which is going to greatly simplify your programming experience. Rather than jumping straight into your first program, we instead want to touch on these foundational topics. Let’s begin by looking at Objective-C, the SDK’s programming language, then by examining some of the basics of the iPhone OS, which contains that set of iPhone frameworks.


Jumping ahead

If you’d prefer to immediately dive into your first iPhone program, which will of course be Hello, World!, then simply head on to the next chapter. You can then pop back here to see what it all means.


10.2. Introducing Objective-C

All of the SDK’s programming is done in Objective-C, a programming language created primarily by Brad Cox and Tom Love in the early 1980s. It’s a full superset of C, allowing you to write any traditional C code. It adds powerful object-oriented capabilities as well. These extensions come by way of the design philosophies of Smalltalk, one of the earliest object-oriented languages. Because of its origin beyond the standard boundaries of C, Objective-C’s messaging code may look a little strange to you at first, but once you get the hang of it, you’ll discover that it’s elegant and easy-to-read, providing some nice improvements over traditional ANSI C code.

Although this overview will give you enough to get started with Objective-C, it can’t provide all the details, particularly for more complex functionality like properties and categories. If you need more information than we’ve been able to provide, take a look at Apple’s own references on the topic, particularly “Object-Oriented Programming with Objective-C” and “The Objective-C 2.0 Programming Language,” both of which can be found in Apple’s iPhone developer library.

10.2.1. The big picture

Let’s start with a look at Objective-C’s big picture. It’s an object-oriented language, which means it’s full of classes and objects, instance variables, and methods. If you need a refresher on any of these topics, check section 9.2 in chapter 9.

As implemented by Apple and used throughout the iPhone OS’s frameworks, Objective-C is built entirely around objects. Windows, views, buttons, sliders, and controllers will all be exchanging information with each other, responding to events and passing actions in order to make your program run.

A header (.h) file and a source code (.m) file together represent each object in Objective-C. Sometimes you’ll access standard classes of objects that come built into the iPhone OS frameworks, but often you’ll instead subclass objects so that you can create new behaviors. When you do this, you’ll add a new header and source code file to your project that together represent the new subclass that you’ve invented.

Although we won’t dwell on it much, note that C++ code can be mixed in with Objective-C code. We leave the specifics of that for the experienced object-oriented programmer (and, as usual, there’s more detail on Apple’s website). You can also freely insert older C syntax; as we’ll discuss shortly, this will become a necessity when you’re working with older libraries.

With all that said, we’re ready to dive into Objective-C’s unique syntax. Table 10.1 summarizes the six major elements of syntax.

Table 10.1. Objective-C code can look quite different from ANSI C; it depends on just a handful of syntactic changes.

Syntax element

Summary

Categories

Categories can be used to add to classes without subclassing.

Classes

Classes define object types in matched .h and .m files.

Messages

Messages send commands to objects in [bracketed] code.

Properties

Properties allow for the easy definition of accessors and mutators.

Protocols

Protocols define methods that a class promises to respond to.

@

@ directives are used by the compiler for a variety of purposes.

We’ll offer a more technical summary at the end of this section, showing all the syntax of these elements. But first, we’ll discuss these syntactic elements at length, in approximate order of importance.

10.2.2. The message

Objective-C’s most important extension to the C programming language is the message. A message is sent when one object asks another to perform a specific action; it’s Objective-C’s equivalent to the procedural functional call. Messages are also the place in which Objective-C’s syntax varies the most from ANSI C standards—which means that once you understand them, you’ll be able to read most Objective-C code.

A simple message call looks like this:

[receiver message];

Here’s a real-life example that we’ll meet in the next chapter:

[window makeKeyAndVisible];

That message sends the window object the makeKeyAndVisible command, which tells it to appear and start accepting user input.

There are three ways in which this message could be slightly more complex. First, it could accept arguments; second, it could be nested; and third, it could be a call to one of a few different recipients.

Messages with Arguments

Many messages will include just a simple command, as in our previous example. But sometimes you’ll want to send one or more arguments along with a message to provide more information on what you want done. When you send a single argument, you do so by adding a colon and the argument after the message, like so:

[receiver message:argument];

Here’s another real-world example:

[textView setText:@"These are the times ..."];

When you want to send multiple arguments, each additional argument is sent following a label, as shown here:

[receiver message:arg1 label2:arg2 label3:arg3];

For example:

[myButton setTitle:@"Goodbye" forState:UIControlStateNormal];

This is the way in which Objective-C’s messages vary the most from C’s functions. You’re really going to come to love it. You no longer need to remember the ordering of the arguments because each gets its own title, clearly marking it. The result is much more readable.

Nested Messages

One of the most powerful elements of Objective-C’s messaging system is the fact that you can nest messages. This allows you to replace either the recipient or the argument of a message (or both) with another message. Then, the return of that nested message automatically fills in the appropriate space of the message it’s nested inside.

Object creation frequently replaces the receiver in this manner:

[[UITextView alloc] initWithFrame:textFieldFrame];

The object created by sending the alloc message to the UITextView class object is then initialized. (We’ll get to class objects in just a moment.)

When you’re passing a color as an argument, you almost always do so by nesting a call to the UIColor class object:

[textView setTextColor:[UIColor colorWithWhite:newColor alpha:1.0]];

Message nesting is a core Objective-C coding style, and thus you’ll see it frequently. It also shows why Objective-C’s bracketed messaging style is cool. With good use of code indentation, it can make complex concepts very readable.

Message Recipients

As we’ve seen over the last couple of examples, there are two different types of objects in Objective-C. Class objects innately exist and each represents one of the classes in your framework. They can be sent certain types of requests, such as a request to create a new object, by sending a message to the class name:

[class message];

For example:

UIButton *myButton =
[UIButton buttonWithType:UIButtonTypeRoundedRect];

Instance objects are what you’re more likely to think of when you hear the term “object.” You create them yourself, and then the majority of your programming time is spent manipulating them. Except for those examples of creating new objects, all of our real-life examples so far have involved instance objects.

In addition to calling an object by name, you can also refer to an object by one of two special keywords: self and super. The first always refers to the object itself, while the second always refers to the class’s parent.

We’ll often see self used internal to a class’s source code file:

[self setText:@"That try mens' souls. "];

We’ll often see super used as part of an overridden method, where the child calls the parent’s method before it executes its own behavior:

[super initWithFrame:frame]

All your message calls should follow one of these four patterns when naming its receiver. They can call something by its class name (for a class method), by its instance name (for an instance method), by the self keyword, or by the super keyword.

Now that you know how to send messages between objects, you’d probably like to know how to create those classes that your objects are instantiated from in the first place. That’s the topic of our next section.

10.2.3. Class definition

As we’ve already noted, each class tends to be represented by a matched pair of files: a header file and a source code file. To define a class, each of these files must contain a special compiler directive, which is always marked in Objective-C with an @ symbol.

First, you define the interface for the class, which is a simple declaration of its public variables and methods. You do this in the header (.h) file. Next, you define the implementation for the class, which is the actual content of all of its methods; this is done in a source (.m) file.

Figure 10.3 shows this bifurcation graphically; we’ll look at it in more depth in the next few sections.

Figure 10.3. Headers and source code files each contain distinctive parts of your Objective-C classes.

The Interface

Interfaces begin with an @interface directive and finish with an @end directive. They contain instance variable declarations in curly brackets, then method declarations. Listing 10.1 shows an example of their usage. It’s the first of several examples that we’re going to offer in this section that will depict a fake class, AppleTree.

Listing 10.1. The @interface directive

We began our interface command with the @interface directive and ended it with the @end directive . Note that our @interface directive included not only our class name, but also the name of its superclass, following a colon. It could also include a list of protocols, a topic we’ll return to later in this section.

The variable declaration is entirely normal. NSString is a type that we’ll meet when we look at the iPhone OS later in this chapter. Note that you don’t have to declare all of your variables in your @interface, but just those instance variables that you want to be accessible outside their methods. You’ll declare variables that are used within only individual methods inside those methods, as you’d expect.

Our method declaration contains a typed description of a method with one argument, matching the syntax we’ve seen for messages already. It also contains one other new element: we’ve started it with a . That means that this is an instance method, which is a method that can only be used by an instance object. Its opposite number, which is marked with a +, is the class method, which is used by a class object.

The id type used as the return of growFruit is another Objective-C innovation. Objective-C allows for dynamic typing, where type is decided at runtime. To support this, it includes the weak type of id, which can be a pointer to any object.

Before we finish our discussion of method declarations, we’d like to mention that, as with variables, you only have to declare those methods that can be called externally. Methods that remain internal to a class can remain hidden if you so desire.

The Implementation

Once you’ve declared a class with an @interface, you can then define it with the @implementation directive. Listing 10.2 shows a brief example of what the implementation might look like for our AppleTree class, including a single example method.

Listing 10.2. The @implementation directive

Our code starts out with the #import directive . This is Objective-C’s variant for the #include macro. It includes the file unless it’s already been included, and is the preferred alternative when using Objective-C. In this case we’ve included AppleTree.h, which should contain the interface we described in listing 10.1. Without including it, we’d need to redefine all of our instance variables and include our super class in the @implementation statement. Thus, the #import helps us avoid redundant code. We’ve also included the Apple.h file so that we can create an Apple.

As with our interface, the implementation code begins with a directive and ends with an end . In between, we describe what our method does , which includes sending a message to the Apple class object.

What We’re Missing

We’ve now got two parts of a puzzle: how to create new classes of objects and how to send messages among instantiated objects. What we’re missing is how to instantiate an object from a class.

Generally object instantiation will follow the same pattern. First, you allocate memory for the object, and then you initiate any variables and perform any other setup. The precise manner in which this is done can vary from class to class. It’s usually a framework that will decide how object creation works—which for our purposes means the iPhone OS. As you’ll see later in this chapter, the iPhone OS specifies two methods for object instantiation: the alloc-init method and the class factory method. We’ll meet each of these soon, when we talk about the iPhone OS, but first let’s finish up with the core syntax of Objective-C.

10.2.4. Properties

What we’ve covered so far should be sufficient for you to understand (and write) most simple Objective-C code. There’s one other major feature in Objective-C that deserves some extended discussion because of its unique syntax: the property.

The Purpose of Properties

Because instance variables are encapsulated, you usually have to write tons of getter and setter methods when doing OOP. This can get tedious, and you must also be careful about consistency so that you don’t have dozens of different syntaxes for your accessors and mutators.

Objective-C offers you a solution to these problems: you can declare an instance variable as a property. When you do so, you standardize the variable’s accessor and mutator methods by automatically declaring a getter and a setter. The setter is called setVariable and the getter is called variable.

For example, if we return to the apples that we’ve been talking about in our major examples, if we defined our NSString *appleType variable as a property, the following declarations would automatically occur:

  • (void)setAppleType:(NSString *)newValue;
  • (NSString *)appleType;

You’ll never see these declarations, but they’re there.

Setting a Property

You declare an instance variable as a property by using the @property directive as part of your @interface statement. Listing 10.3 shows how to do so, in the full context of our example so far.

Listing 10.3. The @property directive

Our header file shows that any property must start with the declaration of an instance variable . The @property directive then repeats that declaration. If you wish, you can stop here. You’ve now implicitly declared your accessor and mutator methods, and you can go and write those methods on your own if you see fit.

Objective-C will also write these methods for you if you just ask it to! This is done with the @synthesize declaration in the @implementation statement . This will create accessor methods that read and set the variable by the simple methods that you’d expect. The setter method is by default of type assign, but you can choose a different method using property attributes, which we’ll talk about down the road.

Using the Accessors

If you’re not doing anything fancy, you can immediately use your class’s default getter and setter methods, as shown in the following three examples:

 NSString *choosenType = [AppleTree appleType];
[AppleTree setAppleType:@"Washington Red"];
[AppleTree setAppleType:myAppleType];

Besides providing you with automatically created accessors and mutators, properties also give you access to a bit of syntactic sugar, which can make using them that much easier.

The Dot Syntax

Objective-C offers a dot syntax that makes it easy to use an object’s accessor and mutator methods (whether you synthesized them or created them yourself). The following are the dot syntax equivalents to the messages that we sent earlier:

NSString *ChoosenType = AppleTree.appleType;
AppleTree.appleType = @"Washington Red";
AppleTree.appleType = myAppleType;

The dot syntax can also be nested, just like you can nest messages. In the following example, the treeType property returns a tree object that has an AppleType property:

Apple1.treeType.AppleType

With that in hand, you should now be able to write simpler and more intuitive code.

Property Complexities

There are several complexities of properties that we’ve opted not to delve into here.

First, property declarations can include attributes. They let you change getter and setter names, change setter assignment methods, set non-atomic accessors (which are accessors which can be interrupted by the CPU scheduler while in usage), and determine whether the property is read-only or read-write. These can all be set as part of the @property line.

Second, there’s another directive called @dynamic, which lets you add accessor and mutator methods at runtime.

Third, it’s possible to override default values that you’ve synthesized through normal method creation as part of your @implementation.

There’s a variety of information on properties in Apple’s Objective-C reference, and if you need to delve into any of these complexities, you should refer to that.

10.2.5. Other compiler directives

We’re almost done with our overview of Objective-C, but we’ve got one other frequently used bit of syntax that we want to alert you to. As we’ve seen, the @ symbol denotes a compile directive. It’s a core part of class definition and it’s required for properties. You’ll also see it in a few other places in Objective-C code.


Warning: Common coding error

We have found that forgetting to mark a string with an @ is our most common error in iPhone programming, so keep an eye out for this one!


Sometimes an @ is used to create variables of certain types. This is most frequently used to create a variable of type NSString *. We saw this in a few of our messaging examples. You just include the @ symbol, followed by the string value you want to set:

NSString *mySample = @"What does this have to do with apples?";

In chapter 14 you’ll also encounter the @selector directive, which is used to create a variable of type SEL. This is a method selector, which is what you use when you want to pass the name of a method as an argument, as will occur when we get to events and actions. A standard usage looks like this:

SEL mySelector = @selector(growFruit:);

There are many other directives that you can use in Objective-C. Our purpose here is merely to highlight those you’re most likely to see in this book and most likely to use in introductory SDK programming.

10.2.6. Categories and protocols

There are two final elements of Objective-C that we think it’s important to at least touch on: the category and the protocol. We’re going to broadly define what they do, but we won’t delve too deeply into their details. To learn more, refer to Apple’s Objective-C documentation.

The Category

Categories are used if you want to add behavior to a class without subclassing. As usual, you do so by creating a new pair of files containing @interface and @implementation code. This time you no longer need to worry about the super class name, but must include a category name in parentheses, as follows:

@interface AppleTree (MyAppleChanges)
@implementation AppleTree (MyAppleChanges)

As a result, the categorized methods and variables that you describe for the classes will be added to the core class definition in your program.

We won’t be using categories in this book.

The Protocol

A protocol is effectively an interface that’s not tied to a class. It declares a set of methods, listing their arguments and their returns. Classes can then state that they’re using the protocol in their own @interface statements. For example, if we had a Growing protocol that was used by plants and animals alike, we could define its usage as follows:

@interface AppleTree : UrTree <Growing>

The AppleTree class would thus be promising that it’d respond to all the methods defined in the Growing protocol.

We won’t be creating any new protocols in this book. However, we will be making use of existing ones because within Apple’s iPhone OS, they’re tied integrally to the MVC model. Views hand off protocol descriptions of how they should be used to view controllers via datasource and delegate properties—both topics that we’ll introduce when we talk about the iPhone OS in just a moment.

With that, we feel like the shine has gone off our apples, so we’re going to be returning to real-life examples when we move on to the iPhone OS. But first, having provided an overview of a whole new programming language in an impossibly short number of pages, we’re going to summarize what we’ve learned.

10.2.7. Wrapping up Objective-C

Table 10.2 summarizes the syntax specifics of the Objective-C elements that we’ve been discussing. This table can serve as a quick reference whenever you want to revisit how Objective-C code works differently from traditional C.

Table 10.2. Objective-C uses many typical object-oriented coding elements, but its syntax is somewhat unique.

Object-oriented element

Syntax

Object messaging

[recipient message];

Class creation

::: .h file :::
@interface class: super
(declarations)
@end
::: .m file :::
@implementation class
(definitions)
@end

Method declaration

- (return type)instancemethod:arguments
+ (return type)classmethod:arguments

Property declaration

@property (declaration)

Property synthesis

@synthesize (property);

Property accessor

[object property];

Property mutator

[object setProperty:value];

Property dot syntax

object.property

Category declaration

@interface class: super (category)
@implementation class: super (category)

Protocol declaration

@interface class: super <protocol>

And with that, we’ve completed our look at the syntax and structure of the Objective-C programming language. However, that’s only half of the foundation you’ll need in order to use the SDK. You also need to be familiar with the specific methods and programming styles provided by the iPhone OS’s extensive set of frameworks.

10.3. Introducing the iPhone OS

In the previous section, we started out not with a discussion of how to define objects, but with a look at how to send messages to them. That was our intent. Apple’s SDK will provide you with a vast library of objects arranged into several frameworks. As a result, you’re going to spend a lot more time sending messages to objects that are ready-made for your use than creating new ones.

Let’s begin our look at the iPhone OS by exploring several of these objects and how they’re arranged.

10.3.1. The anatomy of the iPhone OS

The iPhone OS’s frameworks are divided into four major layers, as shown in figure 10.4.

Figure 10.4. Apple provides you with four layers of frameworks to use when writing iPhone SDK programs.

Each of these layers contains a variety of frameworks that you can access when writing iPhone SDK programs. Generally, you should prefer the higher-level layers when you’re coding (those shown toward the top in the diagram).

Cocoa Touch is the framework that you’ll become most familiar with. It contains the UIKit framework—which is what we’ll spend most of our time on in this book—and the address book UI framework. The UIKit includes window support, event support, and user-interface management, and allows you to create both text and web pages. It further acts as your interface to the accelerometers, the camera, the photo library, and device-specific information.

Media is where you can get access to the major audio and video protocols built into the iPhone. Its four graphical technologies are OpenGL ES, EAGL (which connects OpenGL to your native window objects), Quartz (which is Apple’s vector-based drawing engine), and Core Animation (which is also built on Quartz). Other frameworks of note include Core Audio, Open Audio Library, and Media Player.

Core Services offers the frameworks used in all applications. Many of them are data related, such as the internal Address Book framework. Core Services also contains the critical Foundation framework, which includes the core definitions of Apple’s object-oriented data types, such as its arrays and sets.

Core OS includes the kernel-level software. You can access threading, files, networking, other I/O, and memory.


C vs. Objective-C

Most of your iPhone programming work will be done using the UIKit (UI) or Foundation (NS) frameworks. These libraries are collectively called Cocoa Touch; they’re built on Apple’s modern Cocoa framework, which is almost entirely object-oriented, and in our opinion, much easier to use than older libraries. The vast majority of code in this book will be built solely using Cocoa Touch.

However, you’ll sometimes have to fall back on libraries that are instead based on simple C functionality. Examples include Apple’s Quartz 2D and Address Book frameworks, as well as third-party libraries like SQLite. Expect object creation, memory management, and even variable creation to work differently for these non-Cocoa libraries.

When you fall back on non-Cocoa libraries, you’ll sometimes have to use Apple’s Core Foundation framework, which lies below Cocoa. Your first encounter with Core Foundation will be when we discuss the Address Book framework in chapter 16; we’ll provide more details on how to use Core Foundation at that point.

Although Core Foundation and Cocoa are distinct classes of frameworks, many of their common variable types are “toll-free bridged,” which means that they can be used interchangeably as long as you cast them. Thus, for example, CFStringRef and NSString * are toll-free bridged, as we’ll see when we talk about the Address Book. The Apple class references will usually point out this toll-free bridging for you.


10.3.2. The hierarchy of the iPhone’s objects

Within these frameworks you’ll be able to access an immense wealth of classes that are arranged in a huge hierarchy. You’ll see many of these used throughout this book, and you’ll find a listing of even more in appendix A. Figure 10.5 shows many of the classes that we’ll use over the next several chapters, arranged in hierarchy. They’re just a fraction of what’s available.

Figure 10.5. This hierarchy shows just a small selection of the classes available in the iPhone OS.

As shown in figure 10.5, the objects you’re most likely to use fall into two broad categories.

The NS Classes

The NS classes come from Core Services’ Foundation framework (the Cocoa equivalent of the Core Foundation framework), which contains a huge number of fundamental data types and other objects.

You should use the fundamental Cocoa classes like NSString and NSArray whenever you can, rather than C fundamentals like string * or a plain array. This is because they tend to play nicely with each other and with the UIKit frameworks, and therefore you’re less likely to encounter bizarre errors. Although not shown, NSNumber is another class that you should be aware of. It should be your main numerical object when you’re doing any sort of complex work with a number. It can be used to hold many sorts of numerical values, from floats to integers and more.

The objects that can hold collections of values like NSArray (a numerical array) and NSDictionary (an associative array) are picky about your sticking to their NS brethren. You’ll need to wrap C variables inside Cocoa classes whenever you hand off objects to these arrays. Finally, though NSString can take many sorts of objects when you’re formatting a string, you should be aware that Cocoa objects may require a different formatting string than their C equivalents.

There are two situations when you’ll find that these NS classes can be a deficit. First, if you’re using the Core Foundation framework you’ll often have to take advantage of toll-free bridging by casting variables, as we’ll see starting in chapter 16, when we look at the Address Book. Second, if you’re using external APIs, you may need to convert some classes into their C equivalents. Chapter 16’s look at the SQLite API explores this possibility, with NSString objects often being converted to their UTF-8 equivalent.

The most important of Cocoa’s Foundation objects is the NSObject, which contains a lot of default behavior, include the iPhone’s methods for object creation and memory management, all of which you’ll learn about later in this chapter.

The UI Classes

The second broad category of classes contains the UI classes. These come from Cocoa Touch’s UIKit framework. It includes all of the graphical objects that you’ll be using as well as all the functionality for the iPhone OS’s event model, much of which appears in UIResponder. That’s another topic we’ll return to soon.

10.3.2. Windows and views

As the UI classes demonstrate, the iPhone OS is deeply rooted in the idea of a graphical user interface. Therefore, let’s finish our introduction to the iPhone OS by looking at some of the main graphical abstractions embedded in the UIKit. There are three major abstractions: windows, views, and view controllers.

A window is something that spans the entire screen of the iPhone. There’s only one of them for your application, and it’s the overall container for everything that your application does.

A view is the actual content holder in your application. You may have several of them, each covering different parts of the window or doing different things at different times. They’re all derived from the UIView class. However, don’t just think of a view as a blank container. In actuality, almost any object that you use from the UIKit will be a subclass of UIView that features a lot of behavior all of its own. Among the major subclasses of UIView are UIControls, which give you buttons, sliders, and other items that users may manipulate your program with, and UIScrollableViews, which give users access to more text than can appear at once.

A view controller does what its name suggests. It acts as the controller element of the MVC model and in the process manages a screenful of text, which is sometimes called an application view. As such, it takes care of events and updating for your view.

In this book, we’ve divided view controllers into two types. Basic view controllers are those which just manage a screenful of text (such as the table view controller), while advanced view controllers are those that let a user move around among several pages of text (such as the navigation bar controller and the tab bar controller). Figure 10.6 shows how these three types of objects interrelate.

Figure 10.6. A window contains one or more view controllers or views under the iPhone OS.

Windows, views, and view controllers are ultimately part of a view hierarchy. This is a tree of objects that begins with the window at its root. A simple program might just have a window with a view under it. Most programs will start with a window, have a view controller under that, perhaps supported by additional view controllers, each of which controls views that might have their own subviews. We’ll depict this concept more clearly in chapter 13 when we start looking at the basic view controllers that make this sort of hierarchy possible.

10.4. The iPhone OS’s methods

As you’ve seen, the iPhone OS has a complex and deep structure of classes. Two of the most important are NSObject and UIResponder, which contain many of the methods and properties that you’ll use throughout your programming. Thanks to inheritance, these important functions (and others) can be used by many different iPhone OS objects.

We’ll cover some of these foundational methods here to provide a single reference for their usage, but we’ll be sure to point them out again when we encounter them for the first time in future chapters.

10.4.1. Object creation

We talked earlier about how to define classes, but as we said at the time the specifics of how instance objects are created from classes depend on the implementation of your framework. In the iPhone OS it’s the NSObject that defines how object creation works.

You’re going to meet a few different interfaces that are used to support object creation, but they all ultimately fall back to a two-step procedure that uses the alloc class method and the init instance method. The alloc method allocates the memory for your object, and then returns the object itself. The init method then sets some initial variables in that method. They usually occur through a single, nested message:

id newObject = [[objectClass alloc] init];

The alloc method from NSObject should always do the right thing for you. However, when you write a new subclass you’ll almost always want to write a new init method, because that’s where you define the variables that make your class what it is. Listing 10.4 shows a default setup for an init, which would appear as part of your @implementation.

Listing 10.4. A sample init method for preparing an object

Listing 10.4 shows all the usual requirements of an init method. First, it calls its parent to engage in its class’s usual initialization. Then, it sets any instance variables that should be set . Last, it returns the object, usually with return self; .

The bare init is just one of a few major ways that you can use to create objects in the iPhone OS.

The Argumentative Alternative

Sometimes you’ll want to send an argument with an init. You can do so with an initialization function that you name using the format initWithArgument:. Other than the fact that you’re sending it an argument, it works exactly like a bare init. Here’s another example drawn from actual code we’ll see in upcoming chapters:

[[UITextView alloc] initWithFrame:textFieldFrame];

Initialization methods with arguments allow you to create nonstandard objects set up in ways that you choose. They’re quite common in the UIKit.

One initialization method with an argument deserves a bit of extra mention. initWithCoder: is a special initialization method that’s called whenever you create an object with Interface Builder—and thus is important if you want to do setup for such objects. We’ll return to Interface Builder in chapter 12.

The Factory Method Alternative

A final sort of init supported through the iPhone OS is the factory method. This is a one-step message that takes care of both the memory allocation and initialization for you. All factory methods are named with the format objecttypeWithArgument:. Here’s another real example:

[UIButton buttonWithType:UIButtonTypeRoundedRect];

Class factory methods make messaging a little clearer, but they also have the advantage of taking care of some memory management for you, which is the topic of our next major category of iPhone OS methods.

Object Creation Wrap-Up

We’ve summarized the four major ways that the iPhone OS supports the creation of objects in table 10.3.

Table 10.3. iPhone OS supports several methods that you can use to create objects; different methods will be supported by different classes.

Method

Code

Summary

Simple

[[object alloc] init];

Plain initialization

Argument

[[object alloc] initWithArgument:argument];

An initialization where one or more arguments is passed to the method

Coder

[[object alloc] initWithCoder:decoder];

An initialization with an argument used for Interface Builder objects

Factory

[object objecttypeWithArgument:argument];

A one-step initialization process with an argument

As witnessed by our examples, we’ll use all of these methods as we move through the upcoming chapters.

10.4.2. Memory management

Because of power considerations, the iPhone OS doesn’t support garbage collection. That means that every object that’s created must eventually have its memory released by hand—at least if you don’t want to introduce a memory leak into your program.

The fundamental rule of memory management in the iPhone OS is this: if you allocated the memory for an object, you must release it. This is done via the release message (which is once again inherited from NSObject):

[object release];

You just send that message when you’re all done using an object, and you’ve done your proper duty as a programmer.

You’ll note that we said you only must release the memory if you allocated the memory for it. If you look back to the class factory methods we talked about in the previous section, you’ll see that we didn’t actually allocate the memory for those (because we didn’t send any alloc message), which means we’re not responsible for releasing it. Instead, the class object that actually did the creation has to clean up its memory.

How does the OS know when we’ve finished working with the object it created for us? That’s done through the wonders of autorelease.

The Autorelease Alternative

If you’re responsible for the creation of an object and you’re going to pass it off to some other class for usage, you should autorelease the object before you send it off. This is done with the autorelease method:

[object autorelease];

You’ll typically send the autorelease message just before you return the object at the end of a method. Once an object has been autoreleased, it’s watched over by a special NSAutoreleasePool. The object is kept alive for the scope of the method that it’s been passed to, and then the NSAutoreleasePool cleans it up.

Retaining and Counting

So what if you want to hold onto an object that has been passed to you, and that is going to get autoreleased? In that case, you send it a retain message:

[object retain];

When you do this, you’re saying you want the object to stay around but now you’ve become responsible for its memory as well: you must send a release message at some point to balance your retain.

At this point, we should probably back up and explain the underlying way that the iPhone OS actually manages these memory objects. It does so by maintaining a count of object usage. By default it’s set to 1. Each retain message increases that count by 1, and each release message reduces that count by 1. When the count drops to 0, the memory for the object is freed up.

Therefore, all memory management can be thought of as pairs of messages. If you balance every alloc and every retain with a release, your object will eventually be freed up when you’re done with it.

Memory Management Wrap-Up

Table 10.4 provides a quick summary of the methods we’ve looked at to manage the memory used by your objects.

Table 10.4. The memory management methods help you to keep track of the memory you’re using and clean it up when you’re done.

Method

Summary

alloc

A part of the object-creation routine, but this is what actually allocates the memory for an object’s usage.

autorelease

A request to reduce an object’s memory count by 1 when it goes out of scope; this is maintained by an NSAutorelease pool.

release

Reduces the object’s memory count by 1.

retain

Increases the object’s memory count by 1.

For more information on memory management, including a look at the copy method and how this all interacts with properties, take a look at Apple’s Objective-C references, but what we’ve discussed here should be enough for you to write good Objective-C code.

10.4.3. Event response

The next-to-last category of methods that we’ll examine for the iPhone OS is event response. Unlike with object creation and memory management, we’ll only tackle this issue briefly, because it’s much better documented in chapter 14. The topic is important enough that we want to offer a quick overview of it now.

There are three main ways that events can appear on the iPhone: through bare events (or actions), through delegated events, or through notification.

Whereas the methods of our earlier topics all derived from NSObject, iPhone event response instead comes from the UIResponder object, while iPhone notification comes from the NSNotificationCenter. You won’t have to worry about accessing responder methods and properties as UIResponder is the parent of most UIKit objects, but the NSNotificationCenter will require special access.

Events and Actions

Most user input on the iPhone results in an event being placed into a responder chain. This is a linked set of objects that, for the most part, goes backward up through the view hierarchy. Any input is captured by the first responder, which tends to be the object that the user is directly interacting with. If that object can’t resolve the input, it sends it up to its superview (e.g., a label might send it up to its full-screen view), then to its superview, all the way up the chain (e.g., up through the views, then up through the view controllers). If input gets all the way up the view hierarchy to the window object, it’s next sent on to the application itself, which tends to pass it off to an application delegate as a last resort.

Any of these objects could choose to handle an event, which stops its movement up the responder chain. Following the standard MVC model, you’ll often be building event response into UIViewControllers objects, which are pretty far up the responder chain.

For any UIControl objects, such as buttons, sliders, and toggles, events are often turned into actions. Whereas events report touches to the screen, actions instead report manipulations of the controls and are thus easier to read. Actions follow a slightly different hierarchy of response.

Delegates and Data Sources

There’s another way that events can be sent to an object other than first responder: through a delegate. This is an object (usually a view controller) that says that it’s going to take care of events for another object (usually a view). It’s a close kin to a data source, which is an object (again, usually a view controller) that promises to do the data setup and control for another object (again, usually a view).

Delegation and data sourcing are each controlled by a protocol, which is a set of methods that the delegate or data source agrees to respond to. For example, a table’s delegate might have to respond to a method that alerts it when a row in the table has been selected. Similarly, a table’s data source might describe what all the rows of the table look like.

Delegates and data sources fit cleanly into the MVC model used by Objective-C, as they allow a view to hand off its work to its controller without having to worry about where each of those objects is in the responder chain.

Notifications

Standard event response and delegation represent two ways that objects can be alerted to standard events, such as fingers touching the screen. There’s also a third method that can be used to program many different sorts of activities, such as an iPhone’s orientation changing or a network connection closing: the notification.

Objects register to receive a certain type of notification with the NSNotification-Center, and afterward may process those notifications accordingly. Again, we’ll discuss this topic in chapter 14.

10.4.4. Life-cycle management

By now you know how to create objects using the iPhone OS and how to release their memory when you’re done with them. In that discussion we’ve neglected one other topic: how to recognize when objects are being created and destroyed—starting with your application itself.

Table 10.5 summarizes some of the important messages that will be sent as part of the life cycle of your program. To respond to them, you just fill in the contents of the appropriate methods in either an object or its delegate—which of course will require writing a subclass, and indeed is one of the prime reasons to do so.

Table 10.5. Several important methods let you respond to the life cycle of your application or its individual objects.

Method

Object

Summary

applicationDidFinish-Launching:

UIApplicationDelegate

The application has loaded up; you should create initial windows and otherwise start your program.

applicationDidReceive-MemoryWarning:

UIApplicationDelegate

The application received a low-memory warning; you should free up memory.

applicationWill-Terminate:

UIApplicationDelegate

The application is about to end; you should free up memory and save state.

init

NSObject

The object is being created; you should initiliaze it here.

dealloc

NSObject

The object is freeing up its memory; you should release any objects that haven’t been autoreleased.

Note that we’ve included our old friend init here, since it forms a natural part of the object life cycle. You should look at the individual Apple class references, particularly UIApplicationDelegate, for other methods you might want to respond to when writing your program.

With that, we’ve completed our look at the big picture methods of the iPhone OS. You’ve not yet seen them in real usage, so bookmark these pages as we’ll be referring back to them when we begin actual programming in just a couple of pages.

10.5. Summary

As you begin work with the SDK, you’re not just approaching a new programming language for the iPhone, but a totally new way to create iPhone programs. This means you have to learn an entirely new programming suite.

The SDK is our toolbox. Its most important elements are Xcode, the integrated development environment, and Interface Builder, the graphical object creator.

Objective-C is our programming language. It’s an object-oriented version of C that has some pretty unique syntax thanks to its elegant Smalltalk inspiration. Once you get used to it, you’ll find it simple and easy to read.

The iPhone OS is a layered set of frameworks, which contains everything you need to make your iPhone programming easy. Much of the rest of this book will talk about how to make use of the right frameworks at the right time.

With all of that in your back pocket, you’re ready to start programming using the SDK, a task that will begin on the next page when we dive into the Xcode program that you downloaded at the start of this chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset