Picking an Item from the Photo Library

In addition to using a UIImagePickerController instance to capture new pictures and movies, you can use it to present a media browser that lets a user choose an item from their saved photo albums. The steps you take are similar to those for capturing media, as described in “Taking Pictures and Movies.” The differences are:

This chapter explains how to use an image picker controller and delegate for browsing and choosing saved pictures and movies. If the standard media browsing UI does not suit your needs, you can create a fully custom solution with UIKit and the Assets Library framework. See Assets Library Framework Reference.

Creating and Configuring a Media Browser

Most iOS devices have a photo library. For such devices, whether or not the device has a camera, you can use an image picker controller to present a media browser. As for presenting a camera interface, you must have implemented a delegate object to respond to the user’s interaction with the browsing interface. You can then instantiate and configure an image picker controller by specifying the following options:

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 media browser user interface full screen.

Listing 1  Presenting the media browser interface full screen on iPhone or iPod touch

- (BOOL) startMediaBrowserFromViewController: (UIViewController*) controller
               usingDelegate: (id <UIImagePickerControllerDelegate,
                                   UINavigationControllerDelegate>) delegate {
 
    if (([UIImagePickerController isSourceTypeAvailable:
                 UIImagePickerControllerSourceTypeSavedPhotosAlbum] == NO)
            || (delegate == nil)
            || (controller == nil))
        return NO;
 
    UIImagePickerController *mediaUI = [[UIImagePickerController alloc] init];
    mediaUI.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
 
    // Displays saved pictures and movies, if both are available, from the
    // Camera Roll album.
    mediaUI.mediaTypes =
        [UIImagePickerController availableMediaTypesForSourceType:
            UIImagePickerControllerSourceTypeSavedPhotosAlbum];
 
    // Hides the controls for moving & scaling pictures, or for
    // trimming movies. To instead show the controls, use YES.
    mediaUI.allowsEditing = NO;
 
    mediaUI.delegate = delegate;
 
    [controller presentModalViewController: mediaUI animated: YES];
    return YES;
}

On iPad, you must present the browser interface using a popover as described in initWithContentViewController: and “Presenting and Dismissing the Popover” in UIPopoverController Class Reference. If, on iPad, you attempt to present the browser interface modally (full-screen), the system raises an exception.

Listing 1 displays both still images and movies in the picker, if both are present in the Camera Roll album. To present a picker that displays only movies, for example, instead set the mediaTypes property as follows:

mediaUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];

Using this option, you must first ensure that the device is capable of displaying movies. Do this by calling the availableMediaTypesForSourceType: class method. For a picker that displays only still images, replace the kUTTypeMovie identifier here with kUTTypeImage, or rely on the default value of the mediaTypes property, which is kUTTypeImage.

The startMediaBrowserFromViewController:usingDelegate: example method from Listing 1 is designed to be invoked by an action method such as this:

- (IBAction) showSavedMediaBrowser {
    [self startMediaBrowserFromViewController: self
                                    usingDelegate: self];
}

Notice, as specified in the method signature in Listing 1, that the delegate object must conform to the UIImagePickerControllerDelegate and UINavigationControllerDelegateprotocols.

Implementing a Delegate for the Media Browser

When presented with the standard media browser display for an image picker controller, the user sees a scrolling grid of thumbnails representing the contents of the Camera Roll album. The user options are to cancel the operation or to tap on a thumbnail. If the user taps Cancel, your delegate implementation should simply dismiss the picker—just as you do when presenting the camera interface. Indeed, your imagePickerControllerDidCancel: implementation for an image picker controller is identical whether presenting a camera or a media browser interface. See Listing 2.

If the user taps a thumbnail, what happens next depends on whether the thumbnail represents a still image or a movie.

To respond to the user tapping Choose in an image picker controller configured as a media browser, use code similar to that shown in LISTING.

Listing 2  Delegate method for picked media

- (void) imagePickerController: (UIImagePickerController *) picker
            didFinishPickingMediaWithInfo: (NSDictionary *) info {
 
    NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
    UIImage *originalImage, *editedImage, *imageToUse;
 
    // Handle a still image picked from a photo album
    if (CFStringCompare ((CFStringRef) mediaType, kUTTypeImage, 0)
            == kCFCompareEqualTo) {
 
        editedImage = (UIImage *) [info objectForKey:
                    UIImagePickerControllerEditedImage];
        originalImage = (UIImage *) [info objectForKey:
                    UIImagePickerControllerOriginalImage];
 
        if (editedImage) {
            imageToUse = editedImage;
        } else {
            imageToUse = originalImage;
        }
        // Do something with imageToUse
    }
 
    // Handle a movied picked from a photo album
    if (CFStringCompare ((CFStringRef) mediaType, kUTTypeMovie, 0)
            == kCFCompareEqualTo) {
 
        NSString *moviePath = [[info objectForKey:
                    UIImagePickerControllerMediaURL] path];
 
        // Do something with the picked movie available at moviePath
    }
 
    [[picker parentViewController] dismissModalViewControllerAnimated: YES];
    [picker release];
}

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.