The camera is central to the iPhone experience, It’s the primary camera for the majority of its users. #selfie
In this post we are learn how to get pictures in an app, first by taking a picture and then by browsing the photo library.
Taking a picture
To take a picture you can use the camera screen provided by the iOS SDK. It’s called UIImagePickerController
because it’s a view controller that returns an UIImage
instance.
The first thing you have to do is to create an UIImagePickerController
instance:
class ViewController: UIViewController {
let imagePicker = UIImagePickerController()
...
}
Then set the image picker sourceType
property to .camera
, to make the picker controller use the camera. You will also have to set the delegate in order to be notified when the user selects a picture. After you are done with the setup, present the imagePicker
:
class ViewController: UIViewController {
...
func openCamera() {
imagePicker.sourceType = .camera
imagePicker.delegate = self
present(imagePicker, animated: true)
}
}
You will have to conform to both UIImagePickerControllerDelegate
and UINavigationControllerDelegate
protocols. UINavigationControllerDelegate
is required because UIImagePickerController
is a subclass of UINavigationController
:
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
defer {
picker.dismiss(animated: true)
}
print(info)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
defer {
picker.dismiss(animated: true)
}
print("did cancel")
}
}
Note that you have to dismiss the image picker is the user selected an image.
Asking for permission
The app must ask for permission from the user before accessing the camera.
When it does that it will display a message to the user explaining why it needs to use the camera. You can set this message by setting the NSPhotoLibraryUsageDescription
key in the Info.plist
list of your app.
If you don’t add the NSPhotoLibraryUsageDescription
key you will get an error that looks like this if you try to run that code:
Error: [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.
Open Info.plist
and click the +
on the root node of the plist:
This won’t work on the iOS simulator because it does not have a camera. It’s a good idea to check if the camera is available, you can use the UIImagePickerController.isSourceTypeAvailalbe(_:)
class method for this:
class ViewController: UIViewController {
...
func openCamera() {
guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
print("camera not supported by this device")
return
}
imagePicker.sourceType = .camera
imagePicker.delegate = self
present(imagePicker, animated: true)
}
}
Getting the image form the info dictionary
UIImagePickerController
give a dictionary with information about the selected media. You can find the UIImage
instance representing the selected image on the UIImagePickerControllerOriginalImage
key:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
...
// get the image
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else {
return
}
// do something with it
imageView.image = image
}
Photo Library
To let the user pick an image he previously took, you have to change the sourceType
of the image picker to .photoLibrary
:
func openPhotoLibrary() {
guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
print("can't open photo library")
return
}
imagePicker.sourceType = .photoLibrary
imagePicker.delegate = self
present(imagePicker, animated: true)
}
You have to set the NSPhotoLibraryUsageDescription
key in Info.plist
, same as for the camera. If you don’t you’ll get this error:
Error: [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.
Since we are using UIImagePickerController
for this task as well, we have to photo selection or canceling with the same delegate methods.
Conclusion
UIImagePickerController
is a system component that allow you to take pictures or retrieve them from the photo library. For more complex applications you might need to use other ways of using the camera like the AVFoundation methods in order to make a custom camera screen or if you want to do more with the photo library than just get an image you will need to use the Photos Framework.
Challenges
- Make an app that gets an image from
UIImagePickerController
and show it on the screen - Load two images one on top of each other and make the one on top 50% transparent in order to combine them
excellent!
Thanks a lot.