Documente Academic
Documente Profesional
Documente Cultură
03/09/2008 17:19
Edit Profile
Log out
Before reading the other sections of this article, you should download the sample (MoveMe) so that you can follow along directly in the source code. You should also have already read the following orientation pages in the iPhone Dev Center to get a basic understanding of iPhone OS and the tools and language you use for development: iPhone OS Overview
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 1 of 11
03/09/2008 17:19
If you are not familiar with the Objective-C programming language, you should also have read Learning Objective-C: A Primer to familiarize yourself with the basic syntax of Objective-C.
In iPhone OS, the ultimate target of your Xcode project is an application bundle, which is a special type of directory that houses your application's binary executable and supporting resource files. Bundles in iPhone OS have a relatively flat directory structure, with most files residing at the top level of the bundle directory. However, a bundle may also contain subdirectories to store localized versions of strings and other language-specific resource files. You do not need to know the exact structure of the application bundle for the purposes of this article, but you can find that information in "The Application Bundle" in iPhone OS Programming Guide if you are interested in it. Building the MoveMe Application To build the MoveMe application and run it in the simulator, do the following: 1. Open the MoveMe.xcodeproj file in Xcode. 2. In the project toolbar, make sure the simulator option is selected in the Active SDK menu. (If the Active SDK menu does not appear in the toolbar, choose Project > Set Active SDK > Simulator.) 3. Select Build > Build and Go (Run) from the menu, or simply click the Build and Go button in the toolbar. When the application finishes building, Xcode loads it into the iPhone simulator and launches it. Using your mouse, you can click the Welcome button and drag it around the screen to see the application's behavior. If you have a device configured for development, you can also build your application and run it on that device. For information about how to configure devices for development and load applications, see "Development Environment" in iPhone OS Programming Guide. A Word About Memory Management iPhone OS is primarily an object-oriented system, so most of the memory you allocate is in the form of Objective-C objects. Objects in iPhone OS use a referencecounting scheme to know when it is safe to free up the memory occupied by the object. When you first create an object, it starts off with a reference count of 1. Clients receiving that object can opt to retain it, thereby incrementing its reference count by 1. If a client retains an object, the client must also release that object when it is no longer needed. Releasing an object decrements its reference count by 1. When an object's reference count equals 0, the system automatically reclaims the memory for the object.
Note: iPhone OS does not support memory management using the garbage collection feature that is in Mac OS X v10.5 and later.
If you want to allocate generic blocks of memorythat is, memory not associated with an objectyou can do so using the standard malloc library of calls. As is the case with any memory you allocate using malloc , you are responsible for releasing that memory when you are done with it by calling the free function. The
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 2 of 11
03/09/2008 17:19
case with any memory you allocate using malloc , you are responsible for releasing that memory when you are done with it by calling the free function. The system does not release malloc-based blocks for you. Regardless of how you allocate memory, managing your overall memory usage is more important in iPhone OS than it is in Mac OS X. Although iPhone OS has a virtual memory system, it does not use a swap file. This means that code pages can be flushed as needed but your application's data must all fit into memory at the same time. The system monitors the overall amount of free memory and does what it can to give your application the memory it needs. If memory usage becomes too critical though, the system may terminate your application. However, this option is used only as a last resort, to ensure that the system has enough memory to perform critical operations such as receiving phone calls. For more information about how to allocate objects in iPhone OS, see Cocoa Fundamentals Guide. For information and tips on how to improve your application's memory usage, see "Managing Your Memory Usage" in iPhone OS Programming Guide.
int main(int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal; }
The application delegate object works in tandem with the standard UIApplication object to respond to changing conditions in the application. The application object does most of the heavy lifting, but the delegate is responsible for several key behaviors, including the following: Setting up the application's window and initial user interface
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 3 of 11
03/09/2008 17:19
At launch time, the most immediate concern for the delegate object is to set up and present the application window to the user, which is described in Creating the Application Window. The delegate should also perform any tasks needed to prepare your application for immediate use, such as restoring the application to a previous state or creating any required objects. When the application quits, the delegate needs to perform an orderly shutdown of the application and save any state information needed for the next launch cycle. For more information about the fundamental architecture and life cycle of an iPhone application, see "Core Application Architecture" in iPhone OS Programming Guide.
Listing 2 shows the applicationDidFinishLaunching: method for the MoveMe application, which is defined in the application delegate's implementation file, MoveMeAppDelegate.m . This method creates the main content view for the window and makes the window visible. Showing the window lets the system know that your application is ready to begin handling events. Listing 2 Creating the content view
- (void)applicationDidFinishLaunching:(UIApplication *)application { // Set up the view controller UIViewController *aViewController = [[UIViewController alloc] initWithNibName:@"MoveMeView" bundle:[NSBundle mainBundle]]; self.viewController = aViewController; [aViewController release]; // Add the view controller's view as a subview of the window UIView *controllersView = [viewController view]; [window addSubview:controllersView]; [window makeKeyAndVisible]; }
Note: You can use the applicationDidFinishLaunching: method to perform other tasks besides setting up your application user interface. Many applications use it to initialize required data structures, read any user preferences, or return the application to the state it was in when it last quit. Although the preceding code creates the window's background view and then shows the window, what you do not see in the preceding code is the creation of the PlacardView class that displays the Welcome button. That behavior is handled by the setUpPlacardView method of the MoveMeView class, which is called from the initWithCoder: method called when the MoveMeView object is unarchived from its nib file. The setUpPlacardView method is shown in Listing 3. Part of the initialization of this view includes the creation of a PlacardView object. Because the MoveMeView class provides the background for the entire application, it adds the PlacardView object as a subview. The relationship between the two views not only causes the Welcome button to be displayed on top of the application's background, it also allows the MoveMeView class to handle events that are targeted at the button. Listing 3 Creating the placard view
- (void)setUpPlacardView {
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 4 of 11
03/09/2008 17:19
{ // Create the placard view -- it calculates its own frame based on its image PlacardView *aPlacardView = [[PlacardView alloc] init]; self.placardView = aPlacardView; [aPlacardView release]; placardView.center = self.center; [self addSubview:placardView]; }
For detailed information about creating windows and views, see "Windows and Views" in iPhone OS Programming Guide.
Listing 4 shows the drawRect: method for the PlacardView class. The placardImage member variable contains a UIImage object with the background for the button and the currentDisplayString member variable is an NSString object containing the welcome string. After drawing the image, this method calculates the position of the string within the view. The size of the string is already known, having been calculated when the string was loaded and stored in the textSize member variable. The string is then drawn twiceonce in black and once in whiteusing the drawAtPoint:forWidth:withFont:fontSize:lineBreakMode:baselineAdjustment: method of NSString . Listing 4 Drawing the Welcome button
- (void)drawRect:(CGRect)rect { // Draw the placard at 0, 0 [placardImage drawAtPoint:(CGPointMake(0.0, 0.0))]; /* Draw the current display string. This could be done using a UILabel, but this serves to illustrate the UIKit extensions to NSString. The text is drawn center of the view twice - first slightly offset in black, then in white -- to give an embossed appearance. The size of the font and text are calculated in setupNextDisplayString. */ // Find CGFloat CGFloat CGPoint point at which to draw the string so it will be in the center of the view x = self.bounds.size.width/2 - textSize.width/2; y = self.bounds.size.height/2 - textSize.height/2; point;
// Get the font of the appropriate size UIFont *font = [UIFont systemFontOfSize:fontSize]; [[UIColor blackColor] set]; point = CGPointMake(x, y + 0.5); [currentDisplayString drawAtPoint:point forWidth:(self.bounds.size.width-STRING_INDENT) withFont:font fontSize:fontSize lineBreakMode:UILineBreakModeMiddleTruncation
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 5 of 11
03/09/2008 17:19
lineBreakMode:UILineBreakModeMiddleTruncation baselineAdjustment:UIBaselineAdjustmentAlignBaselines]; [[UIColor whiteColor] set]; point = CGPointMake(x, y); [currentDisplayString drawAtPoint:point forWidth:(self.bounds.size.width-STRING_INDENT) withFont:font fontSize:fontSize lineBreakMode:UILineBreakModeMiddleTruncation baselineAdjustment:UIBaselineAdjustmentAlignBaselines]; }
When you need to draw content that is more complex than images and strings, you can use Quartz or OpenGL ES. Quartz works with UIKit to handle the drawing of vector-based paths, images, gradients, PDF, and other complex content that you want to create dynamically. Because Quartz and UIKit are based on the same drawing environment, you can call Quartz functions directly from the drawRect: method of your view and even mix and match Quartz calls through the use of UIKit classes. OpenGL ES is an alternative to Quartz and UIKit that lets you render 2D and 3D content using a set of functions that resemble (but are not exactly like) those found in OpenGL for Mac OS X. Unlike Quartz and UIKit, you do not use your view's drawRect: method to do your drawing. You still use a view, but you use that view object primarily to provide the drawing surface for your OpenGL ES code. How often you update the drawing surface, and which objects you use to do so, are your decision. For detailed information about each of the drawing technologies and how you use them, see "Graphics and Drawing" in iPhone OS Programming Guide.
The system delivers events to the application's responder objects, which are instances of the UIResponder class. In an iPhone application, your application's views form the bulk of your custom responder objects. The MoveMe application implements two view classes, but only the MoveMeView class actually responds to event messages. This class detects taps both inside and outside the bounds of the Welcome button by overriding the following methods of UIResponder :
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
To simplify its own event-handling behavior, the MoveMe application tracks only the first finger to touch the surface of the device. It does this with the support of the UIView class, which disables multi-touch events by default. For applications that do not need to track multiple fingers, this feature is a great convenience. When multi-touch events are disabled, the system delivers events only related to the first finger to touch the device. Events related to additional touches in a sequence are never delivered to the view. If you want the information for those additional touches, however, you can reenable multi-touch support using the setMultipleTouchEnabled: method of the UIView class. As part of its event-handling behavior, the MoveMeView class performs the following steps: 1. When a touch first arrives, it checks to see where the event occurred. Double-taps outside the Welcome button update the string displayed by the button. Single taps inside the button center the button underneath the finger and trigger an initial animation to enlarge the button. All other touches are ignored. 2. If the finger moves and is inside the button, the button's position is updated to match the new position of the finger.
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 6 of 11
03/09/2008 17:19
3. If the finger was inside the button and then lifts off the surface of the device, an animation moves the button back to its original position.
Listing 5 shows the touchesBegan:withEvent: method for the MoveMeView class. The system calls this method when a finger first touches the device. This method gets the set of all touches and extracts the one and only touch object from it. The information in the UITouch object is used to identify in which view the touch occurred (the MoveMeView object or the PlacardView object) and the number of taps associated with the touch. If the touch represents a double tap outside the button, the touchesBegan:withEvent: method calls the setupNextDisplayString method to change the welcome string of the button. If the event occurred inside the Welcome button, it uses the animateFirstTouchAtPoint: method to grow the button and track it to the touch location. All other touch-related events are ignored. Listing 5 Handling an initial touch event
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // We only support single touches, so anyObject // retrieves just that touch from touches UITouch *touch = [touches anyObject]; // Only move the placard view if the touch was in the placard view if ([touch view] != placardView) { // In case of a double tap outside the placard view, // update the placard's display string if ([touch tapCount] == 2) { [placardView setupNextDisplayString]; } return; } // Animate the first touch CGPoint touchPoint = [touch locationInView:self]; [self animateFirstTouchAtPoint:touchPoint]; }
Listing 6 shows the touchesMoved:withEvent: method of the MoveMeView class. The system calls this method after the finger has touched the device and in response to it moving from its original location. The MoveMe application tracks only those movements that occur within the Welcome button. As a result, this method checks the location of the event and uses it to adjust the center point of the PlacardView object. The movement of the view causes it to be redrawn at the new location automatically. Listing 6 Responding to movement from a touch
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; // If the touch was in the placardView, move the placardView // to its location if ([touch view] == placardView) { CGPoint location = [touch locationInView:self]; placardView.center = location; return; } }
When the user's finger finally lifts from the screen, the MoveMe application responds by triggering an animation to move the button back to its starting position in the center of the application's window. Listing 7 shows the touchesEnded:withEvent: method that initiates the animation. Listing 7 Releasing the Welcome button
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; // If the touch was in the placardView, bounce it back to the center if ([touch view] == placardView) { // Disable user interaction so subsequent touches // don't interfere with animation self.userInteractionEnabled = NO; [self animatePlacardViewToCenter]; return; } }
To simplify the event handling process for the application, the touchesEnded:withEvent: method disables touch events for the view temporarily while the button animates back to its original position. If it did not do this, each of the event-handling methods would need to include logic to determine whether the button was in the middle of an animation and, if so, cancel the animation. Disabling user interactions for the short time it takes the button to travel back to the center of the screen simplifies the event handling code and eliminates the need for the extra logic. Upon reaching its original position, the animationDidStop:finished:
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 7 of 11
03/09/2008 17:19
the screen simplifies the event handling code and eliminates the need for the extra logic. Upon reaching its original position, the animationDidStop:finished: method of the MoveMeView class reenables user interactions so that the event cycle can begin all over again. For more information on handling events in iPhone OS, see "Event Handling" in iPhone OS Programming Guide.
Listing 8 shows the animation code used to pulse the Welcome button when it is first touched. This method sets the duration of the animation and then applies a transform to the button that scales it to its new size. When this animation completes, the animation infrastructure calls the growAnimationDidStop:finished:context: method of the animation delegate, which completes the pulse animation by shrinking the button slightly and moving the placard view under the touch. Listing 8 Animating the Welcome button
- (void)animateFirstTouchAtPoint:(CGPoint)touchPoint { #define GROW_ANIMATION_DURATION_SECONDS 0.15 NSValue *touchPointValue = [[NSValue valueWithCGPoint:touchPoint] retain]; [UIView beginAnimations:nil context:touchPointValue]; [UIView setAnimationDuration:GROW_ANIMATION_DURATION_SECONDS]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector: @selector(growAnimationDidStop:finished:context:)]; CGAffineTransform transform = CGAffineTransformMakeScale(1.2, 1.2); placardView.transform = transform; [UIView commitAnimations]; } - (void)growAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { #define MOVE_ANIMATION_DURATION_SECONDS 0.15 [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:MOVE_ANIMATION_DURATION_SECONDS]; placardView.transform = CGAffineTransformMakeScale(1.1, 1.1); // Move the placard view under the touch NSValue *touchPointValue = (NSValue *)context; placardView.center = [touchPointValue CGPointValue]; [touchPointValue release]; [UIView commitAnimations]; }
For more information about using the built-in view-based animations, see "Animating Views" in iPhone OS Programming Guide. For more information about Core Animation, see "Applying Core Animation Effects" in iPhone OS Programming Guide.
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 8 of 11
03/09/2008 17:19
<?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>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>1.0</string> <key>UIStatusBarHidden</key> <true/> <key>NSMainNibFile</key> <string>MainWindow</string> </dict> </plist>
Note: You can edit the contents of your application's Info.plist file using TextEdit, which displays the XML contents of the file as shown in The contents of the Info.plist file, or the Property List Editor, which displays the file's keys and values in a table. Xcode also provides access to some of these attributes in the information window for your application target. To view this window, select your application target (in the Targets group) and choose File > Get Info. The Properties tab contains some (but not all) of the properties in the Info.plist file. For information about configuring your application's Info.plist file, see "The Information Property List" in iPhone OS Programming Guide. With this final piece in place, you now have all of the basic information needed to create your own functional iPhone application. The next step is to expand on the information you learned here by learning more about the features of iPhone OS. The applications you create should take advantage of the built-in features of iPhone OS to create a pleasant and intuitive user experience. Some of these features are described in Taking Your Applications Further, but for a complete list, and for information on how to use them, see iPhone OS Programming Guide.
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 9 of 11
03/09/2008 17:19
Although you might not think measuring changes in acceleration would be very useful, in reality there is a lot you can do with the information. The force of gravity is constantly trying to pull objects to the ground. This force results in a measurable amount of acceleration toward the ground even when the device is at rest. By tracking which accelerometers are registering this acceleration, and the extent of that acceleration, you can detect the physical orientation of a device in 3D space with a fair amount of accuracy. You can then apply this orientation as input to your application. The system uses the accelerometers to monitor a device's current orientation and to notify your application when that orientation changes. If your application's interface can be displayed in both landscape and portrait mode, you should incorporate view controllers into your basic design. The UIViewController class provides the infrastructure needed to rotate your interface and adjust the position of views automatically in response to orientation changes. If you want access to the raw accelerometer data directly, you can do so using the shared UIAccelerometer object in UIKit. The UIAccelerometer object reports the current accelerometer values at a configurable interval. You can also use the data to detect the device's orientation or to detect other types of instantaneous motion, such as the user shaking the device back and forth. You can then use this information as input to a game or other application. For examples of how to configure the UIAccelerometer object and receive accelerometer events, see "Accessing Accelerometer Events" in iPhone OS Programming Guide. Accessing the User's Contacts The user's list of contacts is an important resource that all system applications share. The Phone, Mail, and SMS Text applications use it to identify people the user needs to contact and to facilitate basic interactions such as starting a phone call, email, or text message. Your own applications can access this list of contacts for similar purposes or to get other information relevant to your application's needs.
iPhone OS provides both direct access to the user's contacts and indirect access through a set of standard picker interfaces. Using direct access, you can obtain the contact information directly from the contacts database. You might use this information in cases where you want to present contact information in a different way or filter it based on application-specific criteria. In cases where you do not need custom interface, however, iPhone OS also provides the set of standard system interfaces for picking and creating contacts. Incorporating these interfaces into your applications requires little effort but makes your application look and feel like it's part of the system. You access the user's contact information using the Address Book and Address Book UI frameworks. For more information about these frameworks, see Address Book Framework Reference and Address Book UI Framework Reference. Getting the User's Current Location Devices that run iPhone OS are meant for users on the go. Therefore the software you write for these devices should also take this fact into account. And because the Internet and web make it possible to do business anywhere, being able to tailor information for the user's current location can make for a compelling user experience. After all, why list coffee shops in New York for someone who is thirsty and currently in Los Angeles? That's where the Core Location framework can help.
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 10 of 11
03/09/2008 17:19
The Core Location framework monitors signals coming from cell phone towers and Wi-Fi hotspots and uses them to triangulate the user's current position. You can use this framework to grab an initial location fix only, or you can be notified whenever the user's location changes. With this information, you can filter the information your application provides or use it in other ways. For an example of how to get location data in your application, see "Getting the User's Current Location" in iPhone OS Programming Guide. Playing Audio and Video iPhone OS supports audio features in your application through the Core Audio and OpenAL frameworks, and provides video playback support using the Media Player framework. Core Audio provides an advanced interface for playing, recording, and manipulating sound and for parsing streamed audio. You can use it to play back simple sound effects or multichannel audio, mix sounds and position them in an audio field, and even trigger the vibrate feature of an iPhone. If you are a game developer and already have code that takes advantage of OpenAL, you can use your code in iPhone OS to position and play back audio in your games. The Media Player framework is what you use to play back full-screen video files. This framework supports the playback of many standard movie file formats and gives you control over the playback environment, including whether to display user controls and how to configure the aspect ratio of video content. Game developers might use this framework to play cut scenes or other prerendered content, while media-based applications can also use this framework to play back movie files.
For information about the media technologies in iPhone OS, see "Audio and Video Technologies" in iPhone OS Programming Guide. Taking Pictures with the Built-in Camera The Camera application on iPhone lets users take pictures and store them in a centralized photo library, along with the other pictures they upload from their computer. And although the iPod touch has no camera, it does have a photo library to hold the user's uploaded pictures. iPhone OS provides access to both of these features through the UIImagePickerController class in the UIKit framework.
The UIImagePickerController class provides the implementation for both the camera and photo library interfaces for your application. These are the standard system interfaces used by other applications, including the Camera and Photos applications. When you display the picker interface, the picker controller takes care of all of the required user interactions and returns the resulting image to your application. For information on how to use the picker interfaces, see "Taking Pictures with the Camera" and "Picking a Photo from the Photo Library" in iPhone OS Programming Guide.
http://developer.apple.com/iphone/gettingstarted/docs/creatingiphoneapps.action
Page 11 of 11