Taking Pictures and Movies
Taking a picture or movie with an image picker controller is a three part process that proceeds as an interplay between your code and the system:
You instantiate and modally present a camera interface—an instance of the
UIImagePickerController
class.The system manages the camera interface and the user’s interaction with it. In typical use, the user either takes a picture or movie, or cancels the operation.
The system invokes your image picker controller delegate object’s methods, which in turn handle the results of the user’s interaction—for example, by saving a new picture to the Camera Roll album. The delegate is also responsible for dismissing the camera interface.
A default image picker controller includes a variety of features, as shown in Figure 1.
This chapter explains how to use a default image picker controller and delegate for taking pictures and movies. (Movie recording is available starting in iOS 3.0 on supported devices).
To learn how to instead use the AV Foundation framework for fully-customized media capture, see Media Capture and Access to Camera in AVFoundation Programming Guide.
Creating and Configuring a Camera Interface
To present a camera interface, you must first ensure that three things are in place:
The device your app is running on must have a camera.
If taking pictures or movies is essential to your app, specify that by configuring the
UIRequiredDeviceCapabilities
key in your app’sInfo.plist
property list file. See UIRequiredDeviceCapabilities in Information Property List Key Reference for the various camera characteristics you can specify as required.If capturing media is incidental to your app—that is, if your app remains useful even if the device doesn’t have a camera—then your code should follow an alternate path when running on a device without a camera.
The device’s camera must be available for you to use, which you can test by way of the
isSourceTypeAvailable:
class method of theUIImagePickerController
class.You must have implemented a delegate object to respond to the user’s interaction with the image picker controller. (See Implementing a Delegate for the Camera Interface.)
With those prerequisites satisfied, create and then configure an image picker controller by specifying the following options:
Source type To configure the picker for media capture as opposed to browsing saved media, set its
sourceType
property toUIImagePickerControllerSourceTypeCamera
.Media types To specify whether the user can take still images, movies, or both, set the
mediaTypes
property to an array containing identifiers for the desired types. The valid values for elements of the array arekUTTypeImage
andkUTTypeMovie
.However, before setting this property, check which media types are available by calling the
availableMediaTypesForSourceType:
class method. If you set themediaTypes
property to an empty array, or to an array in which none of the media types is available for the current source, the system throws an exception.Editing controls To specify whether the camera interface should offer the user controls for moving and scaling the captured picture, or for trimming the captured movie, set the
allowsEditing
property toYES
(to provide editing controls) or toNO
.When using built-in editing controls, the image picker controller enforces certain options. For still images, the picker enforces a square cropping as well as a maximum pixel dimension. For movies, the picker enforces a maximum movie length and resolution. If you want to let the user edit full-size media, or specify custom cropping, you must provide your own editing UI.
Delegate object Finally, assign your delegate object to the image picker controller’s
delegate
property.
Listing 1 verifies the prerequisites are satisfied by way of its method signature and a conditional test, and goes on to instantiate, configure, and asynchronously present the camera user interface full screen.
Listing 1 Presenting the camera interface full screen
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller |
usingDelegate: (id <UIImagePickerControllerDelegate, |
UINavigationControllerDelegate>) delegate { |
if (([UIImagePickerController isSourceTypeAvailable: |
UIImagePickerControllerSourceTypeCamera] == NO) |
|| (delegate == nil) |
|| (controller == nil)) |
return NO; |
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init]; |
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera; |
// Displays a control that allows the user to choose picture or |
// movie capture, if both are available: |
cameraUI.mediaTypes = |
[UIImagePickerController availableMediaTypesForSourceType: |
UIImagePickerControllerSourceTypeCamera]; |
// Hides the controls for moving & scaling pictures, or for |
// trimming movies. To instead show the controls, use YES. |
cameraUI.allowsEditing = NO; |
cameraUI.delegate = delegate; |
[controller presentModalViewController: cameraUI animated: YES]; |
return YES; |
} |
Listing 1 provides a picker that lets the user capture still images and movies, if both are available on the device. To instead present a picker that captures only movies, for example, ensure that movie capture is available and then set the mediaTypes
property as follows:
cameraUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil]; |
(To ensure that movie capture is available, call the availableMediaTypesForSourceType:
class method.)
For a picker that captures only still images, replace the kUTTypeMovie
identifier here with kUTTypeImage
, or rely on the default value of the mediaTypes
property, which is kUTTypeImage
.
The startCameraControllerFromViewController:usingDelegate:
example method from Listing 1 is designed to be invoked by an action method such as this:
- (IBAction) showCameraUI { |
[self startCameraControllerFromViewController: self |
usingDelegate: self]; |
} |
Notice, as specified in the method signature in Listing 1, that the delegate object must conform to the UIImagePickerControllerDelegate
and UINavigationControllerDelegate
protocols.
The result of the startCameraControllerFromViewController:usingDelegate:
example method is that the system modally displays the standard camera interface, including controls for capturing media or canceling, as shown in Figure 1.
Implementing a Delegate for the Camera Interface
When the user taps a button in the camera interface to accept a newly captured picture or movie, or to just cancel the operation, the system notifies the delegate of the user’s choice. The system does not, however, dismiss the camera interface. The delegate must dismiss it by calling the dismissModalViewControllerAnimated:
method and must release the interface as well. It is for this reason that, typically, you make the view controller that presents the camera interface serve double-duty as the delegate.
Listing 2 shows example implementations of delegate methods for an image picker controller. The imagePickerController:didFinishPickingMediaWithInfo:
implementation includes code for saving a still image or a movie, depending on what the user captured.
Listing 2 Delegate methods for a camera interface
@implementation CameraViewController (CameraDelegateMethods) |
// For responding to the user tapping Cancel. |
- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker { |
[[picker parentViewController] dismissModalViewControllerAnimated: YES]; |
[picker release]; |
} |
// For responding to the user accepting a newly-captured picture or movie |
- (void) imagePickerController: (UIImagePickerController *) picker |
didFinishPickingMediaWithInfo: (NSDictionary *) info { |
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType]; |
UIImage *originalImage, *editedImage, *imageToSave; |
// Handle a still image capture |
if (CFStringCompare ((CFStringRef) mediaType, kUTTypeImage, 0) |
== kCFCompareEqualTo) { |
editedImage = (UIImage *) [info objectForKey: |
UIImagePickerControllerEditedImage]; |
originalImage = (UIImage *) [info objectForKey: |
UIImagePickerControllerOriginalImage]; |
if (editedImage) { |
imageToSave = editedImage; |
} else { |
imageToSave = originalImage; |
} |
// Save the new image (original or edited) to the Camera Roll |
UIImageWriteToSavedPhotosAlbum (imageToSave, nil, nil , nil); |
} |
// Handle a movie capture |
if (CFStringCompare ((CFStringRef) mediaType, kUTTypeMovie, 0) |
== kCFCompareEqualTo) { |
NSString *moviePath = [[info objectForKey: |
UIImagePickerControllerMediaURL] path]; |
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum (moviePath)) { |
UISaveVideoAtPathToSavedPhotosAlbum ( |
moviePath, nil, nil, nil); |
} |
} |
[[picker parentViewController] dismissModalViewControllerAnimated: YES]; |
[picker release]; |
} |
@end |
If image editing is enabled and the user successfully accepts a newly captured picture, the info parameter of the imagePickerController:didFinishPickingMediaWithInfo:
method contains a dictionary that includes the edited image. Treat this image as the selected image, as done in Listing 2. If you want to store the original image, you can get it from the dictionary, also as shown in the code listing.
Instead of immediately saving the new media item to the user’s Camera Roll as shown in this example, you could instead call custom code to work with the media.
Copyright © 2012 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2012-07-17