iOS’s methods

As you’ve seen, iOS has a complex and deep structure of classes. In this section, we look at object creation, memory management, event response, and lifecycle management.

Two of the most important classes are NSObject and UIResponder, which contain many of the methods and properties you’ll use throughout your programming. Thanks to inheritance, these important functions (and others) can be used by many different iOS objects. We 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 you encounter them for the first time in future topics.

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 iOS, the NSObject class defines how object creation works.

You’ll 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 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. But 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. Here’s a default setup for an init, which would appear as part of your @implementation:


tmp126_thumb

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

The bare init is one of a few major ways you can create objects in iOS.

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: (argument). Other than the fact that you’re sending it an argument, it works exactly like a bare init. Here’s another example drawn from code you’ll see in upcoming topics:

tmp127_thumb

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

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

THE FACTORY METHOD ALTERNATIVE

A final sort of init supported through iOS is the factory method (class 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: (argument) Here’s another real example:

tmp128_thumb

Class (or factory) methods make messaging a little clearer. They also have the advantage of handling some memory management, which is the topic of the next major category of iOS methods.

OBJECT CREATION WRAP-UP

We’ve summarized the four major ways that iOS supports the creation of objects in table 1.2. As witnessed by the examples, you’ll use all these methods as you move through the upcoming topics.

Table 1.2 iOS supports several methods that you can use to create objects. Different methods are supported by different classes.

Method

Code

Summary

Simple

tmp12-9

Plain initialization

Argument

tmp12-10

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

Coder

tmp12-11

An initialization with an argument used for Interface Builder objects

Factory

tmp12-12

A one-step initialization process with an argument

Memory management

Because of power considerations, iOS doesn’t support garbage collection. That means 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 iOS is this: if you allocate memory for an object, you must release it. This is done via the release message (which is once again inherited from NSObject):

tmp1213_thumb

Send that message when you’ve finished using an object, and you’ve done your proper duty as a programmer.

Note that we said you must release the memory only if you allocated the memory for it. You are considered to "own" the memory for an object if you created it using a method that contains alloc, new, copy, or mutableCopy. You can free memory for an object using the release message as mentioned earlier; however, an easier way in general is making use of the wonders of autorelease. (Factory methods like UIButton’s buttonWithType: return objects that are already autoreleased, so you don’t need to manage their memory unless you explicitly retain it.)

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:

tmp1214_thumb

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

RETAINING AND COUNTING

What if you want to hold onto an object that has been passed to you and that will be autoreleased? In that case, you send it a retain message:

tmp1215_thumb

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 iOS manages 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’ve finished with it.

WARNING Memory management can be the root cause of the bugs. Instruments is a good tool for attempting to diagnose issues with memory leaks.

Whenever you use the keyword retain or alloc, make sure to release. If the object is already released, don’t try to access the released object. A good habit would be to assign nil to a released object and check the value isn’t nil before accessing the object.

MEMORY MANAGEMENT WRAP-UP

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

Table 1.3 The memory-management methods help you keep track of the memory you’re using and clean it up when you’re finished.

Method

Summary

alloc

Part of the object-creation routine that allocates the memory for an object’s usage.

autorelease

Request to reduce an object’s memory count by 1 when it goes out of scope. This is maintained by an NSAutoreleasePool.

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.A good description of memory-management rules is also found in the "Memory Management Programming Guide" on the Mac Developer Library website.

Event response

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

Events can appear on the iPhone or iPad in three main ways: through bare events (or actions), through delegated events, and through notification. Whereas the methods of our earlier topics all derived from NSObject, event response instead comes from the UIResponder object, whereas notification comes from the NSNotif ication-Center. You won’t have to worry about accessing responder methods and properties because UIResponder is the parent of most UIKit objects, but the NSNotification-Center requires special access.

EVENTS AND ACTIONS

Most user input 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 the user is directly interacting with. If that object can’t resolve the input, it sends it up to its super-view (for example, a label might send it up to its full-screen view), then to its super-view, all the way up the chain (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 to the application itself, which tends to pass it off to an application delegate as a last resort.

Any of these objects can choose to handle an event, which stops its movement up the responder chain. Following the standard MVC model, you’ll often build event response into UIViewController 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 easier to read. Actions follow a slightly different hierarchy of response.

DELEGATES AND DATA SOURCES

Events can be sent to an object in a way other than via a first responder: through a delegate. This is an object (usually a view controller) that says it will take care of events for another object (usually a view). It’s 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 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, because 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. A third method can also be used to program many different sorts of activities, such as the device’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 topic 6.

Lifecycle management

In this discussion, we’ve neglected a topic: how to recognize when objects are being created and destroyed—starting with your application. With multitasking enabled in iOS 4, you can create custom behavior before or after your application enters background mode. We’ll cover more details on this topic in topic 21.

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

Table 1.4 Several important methods let you respond to the lifecycle of your application or its individual objects.

Method

Object

Summary

application:DidFinishLaunching WithOptions:

UIApplicationDelegate

Application has loaded. You should create initial windows and otherwise start your program.

applicationDidReceiveMemoryWarning:

UIApplicationDelegate

Application received a low-memory warning. You should free up memory.

applicationWillTerminate:

UIApplicationDelegate

Application is about to end. You should free up memory and save state.

init:

NSObject

Object is being created. You should initialize it here.

dealloc:

NSObject

Object is freeing up its memory. You should release any objects that haven’t been autoreleased.

Note that we’ve included init: here, because 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 may want to respond to when writing programs.

With that, we’ve completed our look at the big-picture methods of iOS. You’ve not yet seen them in real use, so bookmark these pages—we’ll refer to them when you begin programming in topic 3.

Next post:

Previous post: