Changes

An Example iOS 4 iPhone Camera Application (Xcode 4)

10,691 bytes added, 19:59, 30 March 2011
New page: In the chapter entitled Accessing the iPhone Camera and Photo Library we looked in some detail at the steps necessary to provide...
In the chapter entitled [[Accessing the iPhone Camera and Photo Library (Xcode 4)|Accessing the iPhone Camera and Photo Library]] we looked in some detail at the steps necessary to provide access to the iPhone camera and photo libraries in an iOS 4 application. The purpose of this chapter is to build on this knowledge by working through an example iPhone application that accesses the device’s camera and photo libraries.

== An Overview of the Application ==

The application user interface for this example will consist of an image view and two push buttons. When touched by the user, the first button will display the camera to the user and allow a photograph to be taken which will subsequently be displayed in the image view. The second button will provide access to the camera roll where the user may select an existing photo image. In the case of a new image taken with the camera, this will be saved to the camera roll.

Since we will be covering the playback of video in the next chapter (Video Playback from within an iOS 4 iPhone Application) the camera roll and camera will be restricted to still images in this example. The addition of video support to this application is left as an exercise for the reader at the end of the next chapter.

== Creating the Camera Project ==

Begin the project by launching Xcode and creating a new iPhone iOS application project named camera using the View-based application template.

== Adding Framework Support ==

The application developed in this chapter relies on the MobileCoreServices framework. This can be achieved by selecting the product target entry from the project navigator panel (the top item named ''camera'') and clicking on the Build Phases tab in the main panel. In the ''Link Binary with Libraries'' section click on the ‘+’ button, select the ''MobileCoreServices.framework'' entry from the resulting panel and click on the Add button.

== Configuring Protocols, Outlets and Actions ==

The UIImagePickerController class requires a delegate to be declared that conforms to the UIImagePickerControllerDelegate and UINavigationControllerDelegate protocols. In addition we will need an outlet that provides access to the UIImageView object in the user interface where photos will be displayed. We also need to declare two action methods that will be called when the user touches the buttons and a boolean flag to indicate whether the image needs to be saved or not. We will also need to import the ''MobileCoreServices.h'' file. With these requirements in mind, select the cameraViewController.h file in the main Xcode project navigator and modify it is follows:

<pre>
#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>

@interface cameraViewController : UIViewController
<UIImagePickerControllerDelegate,
UINavigationControllerDelegate>
{
UIImageView *imageView;
BOOL newMedia;
}
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
- (IBAction)useCamera;
- (IBAction)useCameraRoll;
@end
</pre>

== Designing the User Interface ==

The next step in this tutorial is to design the user interface. This is a very simple user interface consisting of an image view and two buttons. Select the ''cameraViewContoller.xib'' file and drag and drop components from the Library window (''View -> Utilities -> Object Library'') onto the view. Position and size the components and set the text on the button so that the user interface resembles the following illustration:


[[Image:xcode_4_camera_ui.jpg]]]]


Next, Ctrl-click on the File’s Owner object and drag the resulting line to the UIImageView object in the view window. Select the imageView outlet from the resulting menu.

Select the Camera button and display the Connections Inspector panel (''View -> Utilities -> Connections Inspector''). Click inside the circle to the right of the Touch Up Inside event and drag the line to the File’s Owner object. Select the useCamera method from the resulting menu. Repeat these steps to connect the Camera Roll button to the useCameraRoll action method.

== Implementing the Action Methods ==

The useCamera and useCameraRoll action methods now need to be implemented. The useCamera method first needs to check that the device on which the application is running has a camera. It then needs to create a UIImagePickerController instance, assign the cameraViewController as the delegate for the object and define the media source as the camera. Since we do not plan on handling videos the supported media types property is set to images only. Finally, the camera interface will be displayed and the UIImagePickerController object released. The last task is to set the newMedia flag to YES to indicate that the image is new and is not an existing image from the camera roll. Bringing all these requirements together, along with the @synthesize directive, gives us the following useCamera method:

<pre>
#import “cameraViewController.h”

@implementation cameraViewController;
@synthesize imageView;
.
.
- (void) useCamera
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentModalViewController:imagePicker
animated:YES];
[imagePicker release];
newMedia = YES;
}
}
.
.
@end
</pre>

The useCameraRoll method is remarkably similar to the previous method with the exception that the source of the image is declared to be UIImagePickerControllerSourceTypePhotoLibrary and the newMedia flag is set to NO (since the photo is already in the library we don’t need to save it again):

<pre>
- (void) useCameraRoll
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
newMedia = NO;
}
}
</pre>

== Writing the Delegate Methods ==

As described in Accessing the iPhone Camera and Photo Library, in order to fully implement an instance of the image picker controller delegate protocol it is necessary to implement some delegate methods. The most important method is the didFinishPickingMediaWithInfo which is called when the user has finished taking or selecting an image. The code for this method in our example is as follows:

<pre>
-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = [info
objectForKey:UIImagePickerControllerMediaType];
[self dismissModalViewControllerAnimated:YES];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
UIImage *image = [info
objectForKey:UIImagePickerControllerOriginalImage];

imageView.image = image;
if (newMedia)
UIImageWriteToSavedPhotosAlbum(image,
self,
@selector(image:finishedSavingWithError:contextInfo:),
nil);
}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie])
{
// Code here to support video if enabled
}
}
-(void)image:(UIImage *)image
finishedSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
if (error) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: @"Save failed"
message: @"Failed to save image"\
delegate: nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
</pre>

The code in this delegate method dismisses the image picker view and identifies the type of media passed from the image picker controller. If it is an image it is displayed on the view image object of the user interface. If this is a new image it is saved to the camera roll. The finishedSavingWithError method is configured to be called when the save operation is complete. If an error occurred it is reported to the user via an alert box.

It is also necessary to implement the imagePickerControllerDidCancel delegate method which is called if the user cancels the image picker session without taking a picture or making an image selection. In most cases all this method needs to do is dismiss the image picker:

<pre>
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissModalViewControllerAnimated:YES];
}
</pre>

== Releasing Memory ==

The final task before trying out the application is to make sure that any memory allocated in the course of execution is released:

<pre>
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.imageView = nil;
}
- (void)dealloc {
[imageView release];
[super dealloc];
}
</pre>

== Building and Running the Application ==

In order to experience the full functionality of this application it will be necessary to install it on a physical iPhone or iPod Touch device with a camera. Steps on performing this are covered in Testing iOS 4 Apps on the iPhone – Developer Certificates and Provisioning Profiles.

Assuming certificates and provisioning are configured, click on the Run button to launch the application. Once application loads, select the Camera button to launch the camera interface:


[[Image:ios_4_iphone_app_camera.jpg|The iPhone camera interface inside an iOS 4 application]]


Once the picture has been taken and selected for use in the application it will appear in the image view object of our application user interface:


[[Image:ios_4_iphone_camera_app_running.jpg|The iPhone camera example after a photo has been taken by the user]]


Selecting the Camera Roll button will provide access to the camera roll of the device where an image selection can be made:


[[Image:ios_4_iphone_app_camera_roll.jpg|The iPhone Camera Roll displayed in an iOS 4 application]]