Lesson 31

Using the Camera and Photo Library

All iOS 9 devices have at least one camera. When a user takes a picture with the camera, the image is stored in the device's photo library. This lesson shows you how to allow the user to pick an image from the photo library or take a new picture with the camera and use it in your application.

The UIKit framework contains a class called UIImagePickerController designed specifically to allow you to access the camera and photo library from your applications. This class presents its own user interface (see Figure 31.1) that allows a user to browse through the photo library or control the camera. All you have to do is present this view controller in your application and provide a delegate method whose methods are called when the user has finished selecting an image.

Two screenshots of iOS device, with Photos menu, with the word Cancel on the right top, and folders Moments and Camera Roll listed; and Camera Roll with 10 images below.

Figure 31.1

The image picker controller can also be used to record videos and access these recorded videos within your application.

Selecting the Image Source

The UIImagePickerController class can be used to access the contents of either the photo library, saved photos album, or the camera. You can specify the source by providing a value for the sourceType property. This value can be one of the following:

  • UIImagePickerControllerSourceType.PhotoLibrary
  • UIImagePickerControllerSourceType.Camera
  • UIImagePickerControllerSourceType.SavedPhotosAlbum

To check if a particular source type is available, use the isSourceTypeAvailable(sourceType: UIImagePickerControllerSourceType) -> Bool class method of the UIImagePickerController class as follows:

let hasCamera:Bool = UIImagePickerController.isSourceTypeAvailable(
UIImagePickerControllerSourceType.Camera)

When the sourceType is set to use the camera, you can specify which camera is to be used if your device has multiple cameras. By default, the image picker uses the rear camera. To find out if front and rear cameras are available, use the isCameraDeviceAvailable(cameraDevice: UIImagePickerControllerCameraDevice) -> Bool class method, as shown in the following code snippet:

let hasFrontCamera:Bool =
UIImagePickerController.isCameraDeviceAvailable(
UIImagePickerControllerCameraDevice.Front);
let hasRearCamera:Bool =
UIImagePickerController.isCameraDeviceAvailable(
UIImagePickerControllerCameraDevice.Rear);

Once you have determined that the camera you want to use is available, you can specify it using the cameraDevice property of the image picker instance. For instance, to use the front camera, use the following code:

imagePicker.cameraDevice = UIImagePickerControllerCameraDevice.Front;

Presenting the Image Picker

To display the image picker as a modal sheet, use the presentViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?) method on your active view controller object:

self.presentViewController(imagePicker, animated: true, completion: nil)

On an iPad, you can also display an image picker in a popover controller. The following code snippet shows how this can be done programmatically from a method in your view controller class:

if UIDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad
{
    imagePicker.modalPresentationStyle = UIModalPresentationStyle.Popover
    self.presentViewController(imagePicker, animated: true, completion: nil)
    // Get the popover presentation controller and configure it.
    let presentationController:UIPopoverPresentationController =
        imagePicker.popoverPresentationController!
    presentationController.permittedArrowDirections =
    UIPopoverArrowDirection.Left
    presentationController.sourceView = self.view
    presentationController.sourceRect = popoverPresetingButton.frame
}

The preceding code assumes that you have imagePicker as an instance of UIImagePickerController and popoverPresentingButton as an outlet in your view controller class.

UIImagePickerController requires a delegate object that implements both the UIImagePickerControllerDelegate and UINavigationControllerDelegate protocols. The former defines two methods that are called when the user has selected an image or selected the Cancel button in the image picker:

func imagePickerController(picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : AnyObject])
func imagePickerControllerDidCancel(picker: UIImagePickerController)

The imagePickerControllerDidCancel(picker: UIImagePickerController) delegate method has one parameter that contains a reference to the image picker controller. A typical implementation of this delegate method dismisses the image picker controller if it was presented modally:

picker.dismissViewControllerAnimated(true, completion: nil)

The imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])delegate method has two parameters, the first of which is a reference to the image picker. The second parameter is an NSDictionary object that contains a UIImage object corresponding to the selected image.

To access this image in this delegate method, you can use code similar to the following to retrieve the value in the dictionary that corresponds to the UIImagePickerControllerOriginalImage key:

let image:UIImage = info[UIImagePickerControllerOriginalImage] as! UIImage

Often, you may want to save this UIImage instance to a file. To do that, you must first obtain an NSData instance that contains the pixels in the UIImage instance in a specific file format. Once you have this NSData instance, you can write it to a file by sending it the writeToFile:atomically: message.

To obtain an NSData instance that contains the image as a PNG file, use the UIImagePNGRepresentation function as follows:

let imageData:NSData = UIImagePNGRepresentation(image)! 

To obtain an NSData instance that contains the image in JPEG format, use the UIImageJPEGRepresentation function as follows:

let imageData:NSData = UIImageJPEGRepresentation(image, 1.0)!

The first parameter to this function is the UIImage instance; the second is a number between 0.0 and 1.0 that indicates the desired JPEG quality, with 0.0 being representing the lowest quality and 1.0 the highest quality.

The following implementation of the imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) delegate method shows how to save the selected image to a PNG file in the Documents directory:

func imagePickerController(picker: UIImagePickerController,
      didFinishPickingMediaWithInfo info: [String : AnyObject])
{
    let image:UIImage = info[UIImagePickerControllerOriginalImage] as!
        UIImage
    let imageData:NSData = UIImagePNGRepresentation(image)!
    let documentsDirectory =
        NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
                                            .UserDomainMask,
                                            true)[0]
    let outFile:String = documentsDirectory + "savedImage.png"
    imageData.writeToFile(outFile, atomically: true)
    picker.dismissViewControllerAnimated(true, completion: nil)
}

If you provide a delegate for the image picker, then you are responsible for dismissing the picker. To do so, add the following line of code:

picker.dismissViewControllerAnimated(true, completion: nil)

to the end of both delegate methods:

  • imagePickerControllerDidCancel(picker: UIImagePickerController)
  • imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])

Try It

In this Try It, you build an iPhone application based on the Single View Application template called ImagePicker that allows the user to select an image from the photo library, or take a picture using the camera and display the image in an image view.

Lesson Requirements

  • Launch Xcode.
  • Create a new iPhone project based on the Single View Application template.
  • Add a UIImageView instance to the scene and an appropriate outlet in the view controller file.
  • Add two UIButton instances to the scene and connect them to appropriate action methods in the view controller class.
  • Allow the user to select an image from the photo library and display the selected image in the image view.
  • Allow the user to take a picture using the camera and display the image in the image view.
  • Hide the camera button if the device does not have a camera.

Hints

  • When creating a new project, you can use your website's domain name as the Company Identifier in the Project Options dialog box.
  • To show the Object library, select View arrow Utilities arrow Show Object Library.
  • To show the assistant editor, select View arrow Assistant Editor arrowShow Assistant Editor.

Step-by-Step