Using UIImagePickerController on iOS

How to use UIImagePickerController to select a photo from the Photo Library on iOS in Objective C and Swift

The simplest way to allow users to select a photo is to use the UIImagePickerController class, which provides a built in UI for users to access their photos.

Doing so is incredibly simple.

  1. Declare that your class conforms to the UIImagePickerControllerDelegate and UINavigationControllerDelegate protocols.
  2. Implement the -imagePickerController:didFinishPickingMediaWithInfo: method.
  3. Create and present an UIImagePickerController view controller class.
  4. Do something with the image returned
- (void)pickPhoto {
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    imagePicker.delegate = self;
    [self presentViewController:imagePicker animated:YES completion:nil];
}
// Implement UIImagePickerControllerDelegate method
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info{
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    self.imageView.image = image;
    [picker dismissViewControllerAnimated:YES completion:nil];
}
func pickPhoto() {
    let imagePicker = UIImagePickerController()
    imagePicker.sourceType = .photoLibrary
    imagePicker.delegate = self
    present(imagePicker, animated: true)
}
// Implement UIImagePickerControllerDelegate method
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any])
    imageView.image = (info[.originalImage] as? UIImage)
    picker.dismiss(animated: true, completion: nil)
}

Footnotes

UIImagePickerControllerSourceType

  • UIImagePickerControllerSourceTypePhotoLibrary (.photoLibrary) allows users to pick from their full photo library, including browsing their albums.
  • UIImagePickerControllerSourceTypeSavedPhotosAlbum (.savedPhotosAlbum) limits the selection to just their chronological 'Moments' screen, camera roll.
  • UIImagePickerControllerSourceTypeCamera (.camera) shows a camera interface so the user can take a picture their and then in the app.

Note: using UIImagePickerControllerSourceTypeCamera (.camera) will crash the app unless the info.plist contains the NSCameraUsageDescription key with the following error message; unlike the other two, which use the act of the user selecting a photo as implied consent to give that photo too the app, and do not prompt for permission since iOS 11, when it was changed to run as a separate process (and so no longer require the NSPhotoLibraryUsageDescription key).

[access] This app has crashed because it attempted to access privacy-sensitive data without a usage description.
The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

Select Photos, Videos or Both

By default UIImagePickerController will only show and select images from a users photo library. However this is actually controlled via the mediaTypes property, which acts as a filter. To select photos and videos you would set the array to include videos.

@import MobileCoreServices; // where kUTTypeImage and kUTTypeMovie are defined
imagePicker.mediaTypes = @[(NSString*)kUTTypeImage, (NSString*)kUTTypeMovie];
import MobileCoreServices
imagePicker.mediaTypes = [(kUTTypeImage as String), (kUTTypeMovie as String)]

To extract the video you'll need to get the UIImagePickerControllerMediaURL (.mediaURL) key from the returning info dictionary, instead of the UIImagePickerControllerOriginalImage (originalImage) value.

NOTE: The developer documentation for the property includes this interesting comment regarding those Live Photos that you've enabled effects like 'Bounce and Loop' on.
If you want to display a Live Photo rendered as a Loop or a Bounce, you must include the kUTTypeMovie identifier.

Checking Capabilities

The UIImagePickerController also includes several class methods to check availability of different features.

if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    // This device has a camera
}
NSArray *mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
// Can this camera capture video, or just Photos (i.e: the first iPhone vs the iPhone 3G)
if UIImagePickerController.isSourceTypeAvailable(.camera) {
    // This device has a camera
}
let mediaTypes:[String]? = UIImagePickerController.availableMediaTypes(for: .camera)
// Can this camera capture video, or just Photos (i.e: the first iPhone vs the iPhone 3G)

Other

There are also more APIs, such as for getting the availability of flash, checking front and back cameras availability, checking the capabilities of each camera separately, and for allowing basic editing of the photo before it is given to your app. Official UIImagePickerController Class Documentation

Limitations

UIImagePickerController is an incredibly useful and convenient class for quickly adding image selection into an app. But it does have limitations:

  • no multi-selection support
  • limited filtering options (only photos, or videos, or both)
  • no direct programmatic access to the photo library (only the photo you are given)
  • limited camera access or UI customization.

If you want any of those features then you'll need to use AVFoundation to make a custom camera UI, or PhotoKit (which will be the subject of the next blog post) to make a custom image picker.