1. Using the Camera
If you open the CityGuide project in Xcode and
look at the viewDidLoad: method in the
AddCityController class, you’ll see
that we set the source of the image picker controller to be the photo
album:
pickerController.sourceType =
UIImagePickerControllerSourceTypeSavedPhotosAlbum;
Changing the source to UIImagePickerControllerSourceTypeCamera
will mean that when you call presentModalViewController:, which presents the UIImagePickerController, the camera interface
rather than the photo album will be presented to the user, allowing him to
take a new picture.
If you want to enable video, you need to add the relevant media type to the array
indicating the media types to be accessed by the picker. By default, this
array contains only the image media
type. The following code should determine whether your device supports a
camera, and if it does, it will add all of the available media types
(including video on the iPhone 3GS) to the media types array. If there is
no camera present, the source will be set to the photo album as
before:
if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
NSArray* mediaTypes =
[UIImagePickerController availableMediaTypesForSourceType:
UIImagePickerControllerSourceTypeCamera];
pickerController.mediaTypes = mediaTypes;
} else {
pickerController.sourceType =
UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickerController.allowsEditing = YES;
}
2. Using the Accelerometer
The iPhone’s accelerometer measures the linear acceleration of the
device so that it can report its roll and pitch, but not its
yaw.
Note:
Yaw, pitch, and
roll refer to the rotation of the device in three
axes. If you think about an aircraft in the sky, pushing the
nose down or pulling it up modifies the pitch angle of the aircraft.
However, if you keep the nose straight ahead, you can also modify the
roll of the aircraft using the flaps; one wing will come up, the other
will go down. Finally, keeping the wings level you can use the tail flap
to change the heading (or yaw) of the aircraft (rotating it in a 2D
plane).
If you are dealing with an iPhone 3GS, which has a digital compass,
you can combine the accelerometer and magnetometer readings to have roll,
pitch, and yaw measurements.
The accelerometer reports three figures: X, Y, and Z (see Figure 1). Acceleration values for each axis
are reported directly by the hardware as G-force values. Therefore, a
value of 1.0 represents a load of approximately 1-gravity (Earth’s
gravity). X corresponds to roll, Y to pitch, and Z to whether the device
is front side up or front side down, with a value of 0.0 being reported
when the iPhone is edge-on.
When dealing with acceleration measurements, you must keep in mind
that the accelerometer is measuring just that: the linear acceleration of
the device. When at rest (in whatever orientation), the figures represent
the force of gravity acting on the device, and correspond to the roll and
pitch of the device (in the X and Y directions at least). But while in
motion, the figures represent the acceleration due to gravity, plus the
acceleration of the device itself relative to its rest frame.
2.1. Writing an Accelerometer Application
Let’s implement a simple view-based application to illustrate how
to approach the accelerometer. Open Xcode and start a new iPhone
project, select a View-based Application template, and name the project
“Accelerometer” when prompted for a name.Before jumping back into Xcode to show you how to use the
accelerometer, we’re going to build the UI for the application.
Double-click on the AccelerometerViewController.xib
NIB file to open it in Interface Builder.
We’re going to both report the raw figures from the accelerometer
and display them using a UIProgressView element. So, drag and drop
three progress bars along with labels for those bars into the View
window. After you do that, it should look something like Figure 2. I’ve used two labels for each
progress bar: one to hold the X, Y, or Z and the other to hold the
accelerometer measurements.
Make sure you’ve saved your changes, and close Interface Builder
and return to Xcode. Click on the
AccelerometerViewController.h interface file to
open it in the Xcode editor. We’re going to declare three UILabel and three UIProgressView variables as IBOutlets. Since they aren’t going to be used
outside the class, there isn’t much point in declaring them as class
properties. We’ll also declare a UIAccelerometer instance. Here’s how the
AccelerometerViewController.h interface file should
look when you are done:
#import <UIKit/UIKit.h>
@interface AccelerometerViewController :
UIViewController <UIAccelerometerDelegate> {
IBOutlet UILabel *xLabel;
IBOutlet UILabel *yLabel;
IBOutlet UILabel *zLabel;
IBOutlet UIProgressView *xBar;
IBOutlet UIProgressView *yBar;
IBOutlet UIProgressView *zBar;
UIAccelerometer *accelerometer;
}
@end
Make sure you’ve saved your changes and click on the corresponding
AccelerometerViewController.m implementation file
to open it in the Xcode editor. We don’t actually have to do very much
here, as Interface Builder is going to handle most of the heavy lifting.
Here’s what the file should look like when you are done:
#import "AccelerometerViewController.h"
@implementation AccelerometerViewController
- (void)viewDidLoad {
accelerometer = [UIAccelerometer sharedAccelerometer];
accelerometer.updateInterval = 0.1;
accelerometer.delegate = self;
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[xLabel release];
[yLabel release];
[zLabel release];
[xBar release];
[yBar release];
[zBar release];
accelerometer.delegate = nil;
[accelerometer release];
[super dealloc];
}
#pragma mark UIAccelerometerDelegate Methods
- (void)accelerometer:(UIAccelerometer *)meter
didAccelerate:(UIAcceleration *)acceleration
{
xLabel.text = [NSString stringWithFormat:@"%f", acceleration.x];
xBar.progress = ABS(acceleration.x);
yLabel.text = [NSString stringWithFormat:@"%f", acceleration.y];
yBar.progress = ABS(acceleration.y);
zLabel.text = [NSString stringWithFormat:@"%f", acceleration.z];
zBar.progress = ABS(acceleration.z);
}
@end
All we need to do now is connect the outlets to the UI elements we
created earlier and we’re done. Make sure you’ve saved your changes to
the code and double-click on the
AccelerometerViewController.xib file to go back
into Interface Builder.
Click on File’s Owner, and go to the Connections Inspector (⌘-2)
and connect the xLabel, yLabel, and zLabel outlets to the appropriate UILabel elements in the View window. Then
connect the xBar, yBar, and zBar outlets to the corresponding UIProgressBar elements, as shown in Figure 3.
OK, we’re done. Save the NIB and return to Xcode. Before you click
the Build and Run button, make sure you’ve configured the project to
deploy onto your iPhone or iPod touch to test it. Since this application
makes use of the accelerometer, and iPhone Simulator doesn’t have one,
we’re going to have to test it directly on the device.
If all goes well, you should see something that looks a lot like
Figure 4.