1. Accelerometer Support
The accelerometer built into the iPhone has proven to be a very
popular feature, especially for game developers. The accelerometer lets the entire device be used as an input
device, with its orientation and movement in space transmitted to an
application for custom handling. The ability to tilt and shake the device
and control applications opens new possibilities for application
developers. The user experience concerns for games are somewhat different
from those for productivity, utility, or media-based applications. In most
cases, accelerometer support for the latter types of applications is a
novelty addition. If your application uses the accelerometer as the sole
means of input for any piece of functionality, you may be alienating users
who aren’t in a position to—or who simply don’t wish to—shake and twist
their phone around to use a piece of software.
Accessing the accelerometer is a very simple process. The
UIAccelerometer class represents access to acceleration
events. You can grab an instance of UIAccelerometer with the singleton method
sharedAccelerometer.
The instance requires a delegate assignment. The UIAccelerometerDelegate interface defines
a single method that must be implemented to handle acceleration events.
The method signature is accelerometer:didAccelerate:. Keep in
mind that the UIAccelerometer
construction method uses a singleton instance, which means there is always
only one instance of the accelerometer in memory. As a side effect, only
one delegate can be set for the accelerometer at a particular moment. This
won’t be a problem in most iPhone applications, but developers are capable
of devising very interesting designs that might lead to unexpected
results. For example, if you have two objects that set themselves as the
delegate of the sharedAccelerometer, the first
assignment will be overwritten by the second:
- (void)setupAccelerometer
{
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
accelerometer.delegate = self;
float updateInterval = 1.0f/24.0f;
accelerometer.updateInterval = updateInterval;
}
- (void)accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration
{
NSLog(@"The acceleration values (x, y, z) are: (%d, %d, %d)",
acceleration.x, acceleration.y, acceleration.z);
}
Using the accelerometer outside immersive game environments will
almost always introduce a new
interaction pattern for mobile users. One such interaction pattern is
shaking the device to clear the screen of user input. A simple way to
shift such a feature from a requirement to a fun enhancement is to add a
button that clears the screen in addition to using the
accelerometer.
NOTE
The accelerometer in the iPhone and iPod Touch can be less
accurate and more inconsistent than you may anticipate. The variability
seems to differ among devices. There are two strategies to compensate
for the lack of consistent accuracy. The first is to use the
accelerometer as an enhancement rather than the sole input mechanism.
Support touch-based options for playing games, adjusting orientation, or
performing other orientation-based tasks. The second strategy is to test
accelerometer code on multiple devices. The accelerometer is a fun and
useful—if imperfect—feature.
2. Rotation Support
You can switch an iPhone between portrait and landscape orientations
by turning the device in increments of 90 degrees. View controllers let developers handle changes in
orientation as they occur, without requiring explicit access to the
accelerometer. The most common behavior when orientation changes from the
primary to the secondary mode is to redraw and refresh the layout of all
onscreen views. This may simply involve changing the position and size of
subviews. A change in orientation can also signal that interaction modes
should be switched, providing a different view of the application
altogether. For example, an application may present a table of football
scores when the device is in portrait mode, and a chart of those scores
when the device is rotated. The decision to change interaction patterns
based on device orientation can be complicated. If the alternate view of
the data is a supplement to the core functionality of the application, it
can be an interesting example of progressive enhancement.
The decision to support rotation should take into account the ways
in which users will interact with an application.
Views that display lots of text should consider supporting rotation,
because iPhone users are accustomed to rotating their devices to increase
either text size or the character count for each line of text. Both
scenarios can improve clarity when reading dense text on a small
screen.
Supporting basic view rotation is very easy. The UIViewController class defines a suite of
methods and properties for handling orientation.
The interfaceOrientation property of each
UIViewController instance represents the current
interface rotation for the view. You should override the shouldAutorotateToInterfaceOrientation:interfaceOrientation
method and return YES for all conditions in which
rotation should occur:
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
// Stop any animations, hot UI objects, or redraw operations
// Prepare for rotation
}
- (void)didRotateFromInterfaceOrientation:
(UIInterfaceOrientation)fromInterfaceOrientation
{
// Restart any animations, hot UI objects, or redraw operations
}
The autorotation mechanism is based on four distinct points.
Developers can take advantage of any combination of those points to
perform additional functionality. For example, you may want to swap a
particular graphic from the screen midway through a rotation sequence. You
can override the following four methods in your UIViewController subclass to support custom
rotation logic:
willRotateToInterfaceOrientation:toInterfaceOrientation:duration
Called before the autorotation sequence begins. Use this callback to prepare for rotation by pausing
expensive redraw operations, disabling touch-sensitive controls or
views, and, if necessary, swapping out the main view with another to
be shown during the rotation animation.
willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
Called before the first half of the rotation—that is, the exit rotation
for the current layout—is animated. Any header and footer bars at
the top and bottom of the view animate out immediately after this
callback.
willAnimateSecondHalfOfRotationToInterfaceOrientation:duration:
Called after the first half but before the second half of the rotation animates.
Any header and footer bars animate back into the frame immediately
after this callback is triggered.
didRotateFromInterfaceOrientation:fromInterfaceOrientation
Called after the autorotation sequence completes and all views are in
place. Use this callback to enable any paused effects,
touch-sensitive controls, and status indicators.
The iPhone device itself often disappears into the background of a
user’s attention, allowing the current application to become the entire
experience. Consider the minor disruption of that focus when requiring
users to rotate the device. The act of pulling back from the device,
rotating it, and resetting focus may seem like a minor distraction, but
it’s significant enough to merit consideration. This concern becomes more
relevant in cases where rotation is required, rather than simply supported
as a progressive enhancement
feature.