Categories
iOS Swift

Taking photos on iOS

This time we will take a look on how to take photos and browse them on iOS.

Using UIImagePickerController

Creating user interface for taking photos consists of presenting an instance of UIImagePickerController. Controller needs a delegate and source type what defines if we are going to take a photo or pick a photo from the library. But even before creating the controller it is required to call isSourceTypeAvailable(_:) class method and verifying if the source type is available. For example, it returns false if picker’s sourceType is set to UIImagePickerController.SourceType.photoLibrary and the library is empty. Makes sense, as there are no photos to pick from.

@IBAction func takePhoto(_ sender: Any) {
openPhotoPicker(withSource: .camera)
}
@IBAction func choosePhoto(_ sender: Any) {
openPhotoPicker(withSource: .photoLibrary)
}
@discardableResult private func openPhotoPicker(withSource source: UIImagePickerController.SourceType) -> Bool {
guard UIImagePickerController.isSourceTypeAvailable(source) else { return false }
let picker: UIImagePickerController = {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = source
return picker
}()
present(picker, animated: true, completion:nil)
return true
}

UIImagePickerControllerDelegate contains two methods we need to implement for handling interactions in image picker. Firstly, consuming taken or picked images and secondly, dismissing the picker. Info dictionary in imagePickerController(_:didFinishPickingMediaWithInfo:) contains quite a many values from images to metadata. All the possible keys can be seen here. As a bare minimum we need to handle editedImage and originalImage keys. If it is required to add the image to photo library, then this can be done by calling UIImageWriteToSavedPhotosAlbum(). This starts an asynchronous operation for adding the image to library. And if needed, it is possible to specify callback when this operation finishes.

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let handleImage: (UIImage?) -> () = { (image) in
self.imageView.image = image
self.imageView.isHidden = (image == nil)
if let image = image {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
}
if let image = info[.editedImage] as? UIImage {
handleImage(image)
}
else if let image = info[.originalImage] as? UIImage {
handleImage(image)
}
else {
handleImage(nil)
}
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
}

Privacy statements

Before going ahead and presenting the image picker it is required to add privacy statements to info.plist. Privacy - Camera Usage Description (NSCameraUsageDescription) is required for using the camera and Privacy - Photo Library Additions Usage Description (NSPhotoLibraryUsageDescription) when using UIImageWriteToSavedPhotosAlbum() for storing photos. Values of those keys are localised descriptions which are shown when app requests to use the camera or when adding the photo to the library.

Summary

Setting up user interface for taking photos is quite easy thanks to UIImagePickerController. All in all it was a three step process: configure picker, add privacy statements and handle images.

Sample app

PhotoTaker (GitHub) Xcode 10, Swift 4.2

References

UIImagePickerControllerDelegate (Apple)
NSCameraUsageDescription
NSPhotoLibraryUsageDescription

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s