Monday, 18 February 2013

Customizing Your Application’s Behavior | iPhone Apps Tutorial pdf

Customizing Your Application’s Behavior

There are several ways to customize your basic application behavior to provide the user experience you want.
The following sections describe some of the customizations that you must make at the application level.

=> Launching in Landscape Mode

Applications in iPhone OS normally launch in portrait mode to match the orientation of the Home screen. If you have an application that runs in both portrait and landscape modes, your application should always launch in portrait mode initially and then let its view controllers rotate the interface as needed based on the device’s orientation. If your application runs in landscape mode only, however, you must perform the following steps to make it launch in a landscape orientation initially.
=> In your application’s Info.plist file, add the UIInterfaceOrientation key and set its value to the landscape mode. For landscape orientations, you can set the value of this key to UIInterfaceOrientationLandscapeLeft or UIInterfaceOrientationLandscapeRight.
=> Lay out your views in landscape mode and make sure that their autoresizing options are set correctly.
=> Override your view controller’s shouldAutorotateToInterfaceOrientation: method and return YES only for the desired landscape orientation and NO for portrait orientations.
The UIInterfaceOrientation property hints to iPhone OS that it should configure the orientation of the application status bar (if one is displayed) as well as the orientation of views managed by any view  controllers at launch time. In iPhone OS 2.1 and later, view controllers respect this property and set their view’s initial orientation to match. Using this property is also equivalent to calling the setStatusBarOrientation:animated: method of UIApplication early in the execution of your applicationDidFinishLaunching: method. 
Note: To launch a view controller–based application in landscape mode in versions of iPhone OS prior to v2.1, you need to apply a 90 degree rotation to the transform of the application’s root view in addition to all the preceding steps. Prior to iPhone OS 2.1, view controllers did not automatically rotate their views based on the value of the UIInterfaceOrientation key. This step is not necessary in iPhone OS 2.1 and later, however.

=> Communicating with Other Applications

If an application handles URLs of a known type, you can use that URL scheme to communicate with the application. In most cases, however, URLs are used simply to launch another application and have it display some information that is relevant to your own application. For example, if your application manages address information, you could send a URL containing a given address to the Maps application to show that location
This level of communication creates a much more integrated environment for the user and alleviates the need for your application to implement features that exist elsewhere on the device.
Apple provides built-in support for the http, mailto, tel, and sms URL schemes. It also supports http–based URLs targeted at the Maps, YouTube, and iPod applications. Applications can register their own custom URL schemes as well. To communicate with an application, create an NSURL object with some properly formatted content and pass it to the openURL: method of the shared UIApplication object. The openURL: method launches the application that has registered to receive URLs of that type and passes it the URL. When the user subsequently quits that application, the system often relaunches your application but may not always do so. The decision to relaunch an application is made based on the user’s actions in the handler application and whether returning to your application would make sense from the user’s perspective.

The following code fragment illustrates how one application can request the services of another application (“todolist” in this example is a hypothetical custom scheme registered by an application):
NSURL *myURL = [NSURL
URLWithString:@"todolist://www.acme.com?Quarterly%20Report#200806231300"];
[[UIApplication sharedApplication] openURL:myURL];
Important: If your URL type includes a scheme that is identical to one defined by Apple, the Apple-provided
application is launched instead of your application. If multiple third-party applications register to handle the same URL scheme, it is undefined as to which of the applications is picked to handle URLs of that type.
If your application defines its own custom URL scheme, it should implement a handler for that scheme as described in “Implementing Custom URL Schemes” (page 35). For more information about the system-supported URL schemes, including information about how to format the URLs, see Apple URL Scheme Reference.

Implementing Custom URL Schemes

You can register URL types for your application that include custom URL schemes. A custom URL scheme is a mechanism through which third-party applications can interact with each other and with the system.
Through a custom URL scheme, an application can make its services available to other applications.
Registering Custom URL Schemes
To register a URL type for your application, you must specify the subproperties of the CFBundleURLTypes property, which was introduced in “The Information Property List” (page 26). The CFBundleURLTypes property is an array of dictionaries in the application’s Info.plist file, with each dictionary defining a URL type the application supports. Table describes the keys and values of a CFBundleURLTypes dictionary.
                        Table : Keys and values of the CFBundleURLTypes property

Figure shows the Info.plist file of an application being edited using the built-in Xcode editor. In this figure, the URL types entry in the left column is equivalent to the CFBundleURLTypes key you would add directly to an Info.plist file. Similarly, the “URL identifier” and “URL Schemes” entries are equivalent to the CFBundleURLName and CFBundleURLSchemes keys.
                          Figure : Defining a custom URL scheme in the Info.plist file

After you have registered a URL type with a custom scheme by defining the CFBundleURLTypes property,
you can test the scheme in the following way:
1. Build, install, and run your application.
2. Go to the Home screen and launch Safari. (In the iPhone simulator you can go to the Home screen by selecting Hardware > Home from the menu.)
3. In the address bar of Safari, type a URL that uses your custom scheme.
4. Verify that your application launches and that the application delegate is sent a application:handleOpenURL: message.

=> Handling URL Requests

The delegate of an application handles URL requests routed to the application by implementing the application:handleOpenURL: method. You especially need the delegate to implement this method if you have registered custom URL schemes for your application.
A URL request based on a custom scheme assumes a kind of protocol understood by those applications requesting the services of your application. The URL contains information of some kind that the scheme-registering application is expected to process or respond to in some way. Objects of the NSURL class, which are passed into the application:handleOpenURL: method, represent URLs in the Cocoa Touch framework. NSURL conforms to the RFC 1808 specification; it includes methods that return the various parts of a URL as defined by RFC 1808, including user, password, query, fragment, and parameter string.

The “protocol” for your custom scheme can use these URL parts for conveying various kinds of information.
In the implementation of application:handleOpenURL: shown in Listing 1-2, the passed-in URL object conveys application-specific information in its query and fragment parts. The delegate extracts this information in this case, the name of a to-do task and the date the task is due and with it creates a model
object of the application.
Handling a URL request based on a custom scheme
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[url scheme] isEqualToString:@"todolist"]) {
ToDoItem *item = [[ToDoItem alloc] init];
NSString *taskName = [url query];
if (!taskName || ![self isValidTaskString:taskName]) { // must have a
task name
[item release];
return NO;
}
taskName = [taskName
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
item.toDoTask = taskName;
NSString *dateString = [url fragment];
if (!dateString || [dateString isEqualToString:@"today"]) {
item.dateDue = [NSDate date];
} else {
if (![self isValidDateString:dateString]) {
[item release];
return NO;
}
// format: yyyymmddhhmm (24-hour clock)
NSString *curStr = [dateString substringWithRange:NSMakeRange(0, 4)];
NSInteger yeardigit = [curStr integerValue];
curStr = [dateString substringWithRange:NSMakeRange(4, 2)];
NSInteger monthdigit = [curStr integerValue];
curStr = [dateString substringWithRange:NSMakeRange(6, 2)];
NSInteger daydigit = [curStr integerValue];
curStr = [dateString substringWithRange:NSMakeRange(8, 2)];
NSInteger hourdigit = [curStr integerValue];
curStr = [dateString substringWithRange:NSMakeRange(10, 2)];
NSInteger minutedigit = [curStr integerValue];
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setYear:yeardigit];
[dateComps setMonth:monthdigit];
[dateComps setDay:daydigit];
[dateComps setHour:hourdigit];
[dateComps setMinute:minutedigit];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *itemDate = [calendar dateFromComponents:dateComps];
if (!itemDate) {
[dateComps release];
[item release];
return NO;
}
item.dateDue = itemDate;
[dateComps release];
}
[(NSMutableArray *)self.list addObject:item];
[item release];
return YES;
}
return NO;
}

Be sure to validate the input you get from URLs passed to your application; see Validating Input in Secure Coding Guide to find out how to avoid problems related to URL handling. To learn about URL schemes  defined by Apple, see Apple URL Scheme Reference.

=> Displaying Application Preferences

If your application uses preferences to control various aspects of its behavior, how you expose those preferences to the user depends on how integral they are to your program.
=> Preferences that are integral to using the application (and simple enough to implement directly) should be presented directly by your application using a custom interface.
=> Preferences that are not integral, or that require a relatively complex interface, should be presented using the system’s Settings application.
When determining whether a set of preferences is integral, think about the intended usage pattern. If you expect the user to make changes to preferences somewhat frequently, or if those preferences play a relatively important role in how the application behaves, they are probably integral. For example, the settings in a game are usually integral to playing the game and something the user might want to change quickly. Because the Settings application is a separate application, however, you would use it only for preferences that you do not expect the user to access frequently.
If you choose to implement preferences inside your application, it is up to you to define the interface and write the code to manage those preferences. If you choose to use the Settings application, however, your application must provide a Settings bundle to manage them.
A settings bundle is a custom resource you include in the top level of your application’s bundle directory.
An opaque directory with the name Settings.bundle, the settings bundle contains specially formatted data files (and supporting resources) that tell the Settings application how to display your preferences. These files also tell the Settings application where to store the resulting values in the preferences database, which your application then accesses using the NSUserDefaults or CFPreferences APIs.
If you implement your preferences using a settings bundle, you should also provide a custom icon for your preferences. The Settings application looks for an image file with the name Icon-Settings.png at the top level of your application bundle and displays that image next to your application name. The image file should be a 29 x 29 pixel PNG image file. If you do not provide this file at the top level of your application bundle, the Settings application uses a scaled version of your application icon (Icon.png) by default.

=> Turning Off Screen Locking

If an iPhone OS–based device does not receive touch events for a specified period of time, it turns off the screen and disables the touch sensor. Locking the screen in this way is an important way to save power. As a result, you should leave this feature enabled except when absolutely necessary to prevent unintended behavior in your application. For example, you might disable screen locking if your application does not receive screen events regularly but instead uses other features (such as the accelerometers) for input.

To disable screen locking, set the idleTimerDisabled property of the shared UIApplication object to YES. Be sure to reset this property to NO at times when your application does not need to prevent screen locking. For example, you might disable screen locking while the user is playing a game but should reenable it when the user is in setup screens or is otherwise not actively playing the game.

No comments: