The Xcode Code Editor

The Xcode Code EditorThe main tool you use to write code for an iPhone application is the Xcode text editor. Apple has gone out of its way to make the text editor as user-friendly as possible, as evidenced by the following list of (quite convenient) features:

 Code Sense: As you type code, you can have the Editor help by inserting text that completes the name of whatever Xcode thinks you’re going to enter.

Using Code Sense can be really useful, especially if you’re like me and forget exactly what the arguments are for a function. When Code Sense is active (it is by default), Xcode uses the text you typed, as well as the context within which you typed it, to provide suggestions for completing what it thinks you’re going to type. You can accept suggestions by pressing Tab or Return. You may also display a list of completions by pressing Escape.

 Code Folding: With code folding, you can collapse code that you’re not working on and display only the code that requires your attention. You do this by clicking in the column to the left of the code you want to hide.

 Switching between header and implementation windows: On the

Toolbar above the code editor, you click the last icon before the lock to switch from. h to. m (header and implementation), and vice versa. While the header lets you see the class’s instance variables and method declarations, you find your actual code in the implementation file. If you look in the Groups & Files pane of the project window, you can see the separate .h and. m files for the four classes we have started with.

 Launching a file in a separate window: Double-click the filename to launch the file in a new window. This enables you folks with big monitors, or multiple monitors, to look at more than one file at a time. You could, for example, look at the method of one class and the method it invokes in the same, or even a different class.

Buckle Up, It’s Time to Code

Buckle Up, It's Time to Code

Previous chapters talk about design principles in general, as well as about the specific iPhone developer tools (Xcode, Interface Builder) available to you. Chapter 5, for example, has you create the skeleton for a fully functioning iPhone application (my ReturnMeTo jewel) — and now you get to flesh it all out with the code necessary for transforming the ReturnMeTo application from something that just sits there and looks pretty to something that actually does something.

A quick refresher peek at Chapter 5 will show you that quite a bit of the ReturnMeTo application is already in place and ready to go. If you click the text field, for example, you do get the keyboard — though you can’t do

Anything with it just yet. Both the text field and the label are automatically created from the nib file — which is great — but somehow you have to accomplish two tasks:

✓ Get what the user enters into the text field.

✓ Display the user input in the label you created.

In effect, you have to connect things up so the left hand knows what the right hand is doing.

Fortunately, the framework was designed to allow you to do this easily and gracefully. The view controller can refer to objects created from the nib file by using a special kind of instance variable (a variable defined as part of a class, with each object of that class having its own copy) referred to as an Outlet. If I want (for example) to be able to access the text field object in my ReturnMeTo application, I take two steps:

1. Declare an outlet in my code.

2. Use Interface Builder to point the outlet to the text field I created earlier.

Then, when my application is initialized, the text field outlet is automatically initialized with a pointer to the text field. I can then use that outlet from within my code to get the text the user entered in the text field.

The fact that a connection between an object and its outlets exists is actually stored in a nib file. When the nib file is loaded, each connection is reconstituted and reestablished — thus enabling you to send messages to the object. iBOutlet is the keyword that tags an instance-variable declaration so the Interface Builder application knows that a particular instance variable is an outlet — and can then enable the connection to it with Xcode.

£

In my code, it turns out I need to create two outlets — one to point to the text field and one to point to the label where I will display the number the user enters. To get this outlet business started, I need to declare it, which I do with the help of the aforementioned iBOutlet keyword.

Okay, I’m guessing you realize that declaring something in programming doesn’t involve standing on a soapbox in Hyde Park and saying something at the top of your lungs. Declaring something code-wise involves. . . writing code. (Y ou knew that.) More specifically, in iPhone application development, declaring something code-wise involves writing code using the Xcode editor — which leads us right to the next section.

In this part

In this part

Ou’re not the only one who dreams of the riches and glory an iPhone application can bring — your author has dreams, too. In this part, I take you through the entire process of developing the small yet real and sort of functional application that you built the user interface for in Part II. Not far down the development trail, you get to see how to add all the features your app needs, and even what to do when you change your mind (whether because you found a better way to do something or your users demanded it). I end up showing you how to get your application running on the iPhone and then into the App Store. All this should keep you out of trouble for a while, but at the end, you can start thinking about a trip around the world by private jet, or something equally reasonable.

Whew!

Whew!Congratulations — you have just gone through the "Classic Comics" version of another several hundred pages of Apple documentation, reference manuals, and how-to guides.

Although there’s a lot left unsaid (though less than you might suspect), what’s in this chapter is enough to not only to get you started but also to keep you going as you develop your own iPhone applications. It provides a frame of reference on which you can hang the concepts I throw around with abandon in upcoming chapters — as well as the groundwork for a deep enough understanding of the application life cycle to give you a handle on the detailed documentation.

Time to move on to the really fun stuff.

BE/?

From "Gee, That’s a Good Idea," to the App Store

The 5th Wave_By Rich Tennant

" Stop – working on ike "Priority "Parking Spot Allocation program. They – want to £ast track the Co££ee "Pot/Cubicle ‘Proximity program.1′

Seeing how memory management works on the iPhone

Seeing how memory management works on the iPhone

One of the main responsibilities of all good little applications is to deal with low memory. So the first line of defense is (obviously) to understand how you as a programmer can help them avoid getting into that state.

In the iPhone OS, each program uses the virtual-memory mechanism found in all modern operating systems. But virtual memory is limited to the amount of physical memory available. This is because the iPhone OS doesn’t store "changeable" memory (such as object data) on the disk to free up space, and then read it in later when it’s needed. Instead, the iPhone OS tries to give the running application the memory it needs — using memory pages that contain read-only contents (such as code), where all it has to do is load the "originals" back into memory when they’re needed. Of course, this may be only a temporary fix if those resources are needed again a short time later.

If memory continues to be limited, the system may also send notifications to the running application, asking it to free up additional memory. This is one of the critical events that all applications must respond to.

Observing low-memory warnings

When the system dispatches a low-memory notification to your application, it is something you must pay attention to. If you don’t, it is a reliable recipe for disaster. (Think of your low-fuel light going on as you approach a sign that says "Next services 100 miles.") UIKit provides several ways of setting up your application so that you receive timely low-memory notifications:

✓ Implement the applicationDidReceiveMemoryWarning: method of your application delegate. Your application delegate could then release any data structure or objects it owns — or notify the objects to release memory they own.

✓ Override the didReceiveMemoryWarning: method in your custom UlViewController subclass. The view controller could then release views — or even other view controllers — that are off-screen.

✓ Register to receive the UIApplicationDidReceiveMemoryWarning Notification: notification. A model object could then release data structures or objects it owns that it doesn’t need immediately and can re-create later.

UIKit Your code

Each of these strategies gives a different part of your application a chance to free up the memory it no longer needs (or doesn’t need right now). As for how you actually get these strategies working for you, while I will mention a strategy for implementing the view controller’s didReceiveMemoryWarning: in Chapter 14, this is something that is dependent on your application’s architecture. That means you’ll need to explore it on your own.

Not freeing up enough memory will result in the iPhone’s OS sending your application the applicationWillTerminate: message and shutting you down. For many applications, though, the best defense is a good offense, and you need to manage your memory effectively and eliminate any memory leaks in your code.

Avoiding the warnings

When you create an object — a window or button for example — memory is allocated to hold that object’s data. The more objects you create, the more memory you use, and the less there is available for additional objects you might need. Obviously, it’s important to make available (deallocate) the memory that an object was using when the object is no longer needed. This is what is meant by memory management.

The Objective-C language — the application-programming language used to develop iPhone applications — uses reference counting to figure out when to release the memory allocated to an object. It’s your responsibility (as a programmer) to keep the memory-management system informed when an object is no longer needed.

Responding to interruptions

Responding to interruptionsVarious events besides termination can interrupt your application to allow the user to respond — for example, incoming phone calls, SMS messages, calendar alerts, or the user pressing the Sleep button on an iPhone. Such interruptions may only be temporary. If the user chooses to ignore an interruption, your application continues running as before. If the user decides to answer the phone or reply to an SMS message, however, your application will be terminated.

Figure 6-8 shows the sequence of events that occurs during the arrival of a phone call, SMS message, or calendar alert. Here’s what that looks like step by step:

1. The system detects an incoming phone call or SMS message, or a calendar event occurs.

2. The system sends your application delegate the applicationWill ResignActive: message.

Because these interruptions cause a temporary loss of control by your application — meaning that touch events are no longer sent to your applications — it is up to you to prevent what is known in the trade as a "negative user experience." For example, if your application is a game, you should pause the game.

3. The system displays an alert panel with information about the event.

The user can choose to ignore the event or respond to it.

4. If the user ignores the event, the system sends your application delegate the applicationDidBecomeActive: message and resumes the delivery of touch events to your application.

You can use this delegate method to restore the application to the state it was in before the interruption. What you do depends on your application. In some applications, it makes sense to resume normal processing. In others — if you’ve paused a game, for example — you could leave the game paused until the user decides to resume play.

5. If the user responds to the event, instead of ignoring it, the system sends your application delegate the applicationWillTerminate: Message.

Your application should do what it needs to do in order to terminate gracefully.

The way the Sleep/Wake button is handled is a little different. When the application enters or resumes from a sleep state, two messages are sent to the application delegate: applicationWillResignActive: and applica-tionDidBecomeActive:, respectively. In this case, your application always resumes, though the user might immediately launch a different application.

Other Runtime Considerations

Other Runtime ConsiderationsLaunch, initialize, process, terminate, launch, initialize, process, terminate. . . it has a nice rhythm to it, doesn’t it? And those are the four major stages of the application’s life cycle. But life isn’t simple — and neither is runtime. To mix things up a bit, your application will also have to come to terms with interruptions and memory management.

BE*

Termination

TerminationGetting stuff to (safely) shut down is another application delegate responsibility. To handle termination, the application delegate implements the delegate method applicationWillTerminate: to save any unsaved data or key application state (where the user is in the application — the current view and stuff like that) to disk. (Okay, I know, the disk in the iPhone is not really a disk; it’s a solid state drive that Apple calls a disk, but if it calls it that, I probably should, too, just so I don’t confuse too many people.). You can also use this method to perform additional cleanup operations, such as deleting temporary files.

Event Processing

Event ProcessingAfter a user launches your application, the functionality provided in the UIKit framework manages most of the application’s infrastructure. Part of the initialization process mentioned in the previous section involves setting up the main run loop and event handling code, which is the responsibility of

The UIApplication object.

When the application is on-screen, it’s driven by external events — say, stubby fingers touching sleek screens, as shown in Figure 6-7. Here’s a rundown of how external events drive an application:

1. You have an event — the user taps a button, for example.

The touch of a finger (or lifting it from the screen) adds a touch event to the application’s event queue, where it’s encapsulated in — placed into — a UIEvent object. There is a UITouch object for each finger touching the screen so you can track individual touches. As the user manipulates the screen with his or her fingers, the system reports the changes for each finger in the corresponding UITouch object.

My advice to you: Don’t let your eyes glaze over here. This UIEvent and UITouch stuff is important, as you’ll discover when I show you how to handle touch events while walking you through building the more advanced parts of the ReturnMeTo application.

2. The run loop monitor dispatches the event.

When there is something to process, the event-handling code of the UIApplication processes touch events by dispatching them to the appropriate responder object — the object that has signed up to take responsibility for doing something when an event happens (when the user touches the screen, for example). Responder objects can include

Instances of UIApplication, UlWindow, UlView, and its subclasses (all which inherit from UlResponder).

3. A responder object decides how to handle the event.

For example, a touch event occurring in a button (view) will be delivered to the button object. The button handles the event by sending an action message to another object — in this case, the UlViewController object. Setting it up this way enables you to use standard button objects without having to muck about in their innards — just tell the button what method you want invoked in your view controller, and you’re basically set.

Processing the message may result in changes to a view, or a new view altogether, or some other kind of change in the user interface. When this happens, the view and graphics infrastructure takes over and processes the required drawing events.

4. You’re sent back to the event loop.

After an event is handled or discarded, control passes back to the run loop. The run loop then processes the next event or puts the thread to sleep if there’s nothing more for it to do.

Operating system

Event queue

Application objects

Figure 6-7:

Processing events in the main run loop.

Initialization

InitializationThe next step is for the UIApplication to send the ReturnMeToApp Delegate applicationDidFinishLaunching: message. Step 5 in Figure 6-6 represents what happens when the applicationDidFinish Launching: method is invoked.

This figure looks exactly like Figure 6-4, except I added a Step 5: putting the view into the window and then making the window visible. At this point, you’d do any other application initialization as well — and return everything to what it was like when the user last used the application.

Fi П П UqkilMndaw. ii lb

Ш s | ш i л О

VrfwUfidf Ms 11bury infp-rrtar ® •

TIE tlripHid

Figure 6-6 is more than just a conceptual diagram, as you can see from Listing 6-1, which shows two instance variables, window, and viewController. These are automatically "filled in" for you when your application is launched. Then, in the applicationDidFinishLaunching: method, the view controller and its view are added to the window, and the window becomes visible. Note that this was generated automatically by Xcode. (I’ll get into what all those strange things like IBOutlet and @property mean in the next chapter.)

Figure 6-6:

The applic ation Did Finish Launch ing: method installs the view in the window and makes the window visible.

Listing 6-1: ReturnMeToAppDelegate

// ReturnMeToAppDelegate. h

#import <UIKit/UIKit. h>

@class ReturnMeToViewController;

@interface ReturnMeToAppDelegate : NSObject

<UIApplicationDelegate> {

UIWindow *window;

ReturnMeToViewController *viewController;

}

@property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet

@end

// ReturnMeToAppDelegate. m

#import "ReturnMeToAppDelegate. h" #import "ReturnMeToViewController. h"

@implementation ReturnMeToAppDelegate @synthesize window; @synthesize viewController;

- (void)applicationDidFinishLaunching:

(UIApplication *)application {

[window addSubview:viewController. view]; [window makeKeyAndVisible];

}

JjJJlBEH

What this does is quite a bit; what it doesn’t do is connect objects added to the user interface with the objects that need to know about them. How does my application access the phone number that the user enters, for example? Of course, I could root around in the code, but it would be much easier to have Interface Builder do it at application launch. I show you how that is (easily) done in the next chapter.

Your goal during startup should be to present your application’s user interface as quickly as possible — quick initialization = happy users. Don’t load large data structures that your application won’t use right away. If your application requires time to load data from the network (or perform other tasks that take noticeable time), get your interface up and running first — and then launch the slow task on a background thread. Then you can display a progress indicator or other feedback to the user to indicate that your application is loading the necessary data or doing something important.

The application delegate object is usually derived from NSObject, the root class (the very base class from which all iPhone application objects are derived), although it can be an instance of any class you like, as long as it adopts the UIApplicationDelegate protocol. The methods of

This protocol correspond to behaviors that are needed during the application life cycle and are your way of implementing this custom behavior. Although you are not required to implement all of the methods of the

UIApplicationDelegate protocol, every application should implement the following critical application tasks:

✓ Initialization, which I have just covered

✓ Responding to interruptions

✓ Responding to low memory warnings

I show you what has to be done to carry out these tasks in the last two sections.