Initializing a UIImagePickerController
@IBAction func pickAnImage(_ sender:Any) {
let pickerController = UIImagePickerController()
present(pickerController, animated: true, completion: nil)
}
UIImagePickerControllerDelegate
When the Image Picker Controller is presented one of two things can happen
- The user might select and image
- The user might cancel and close out
The delegate protocol is pretty straight forward with only two optional methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
Tells the delegate that the user picked a still image or movie.
func imagePickerControllerDidCancel(UIImagePickerController)
Tells the delegate that the user cancelled the pick operation.
To be a delegate of the UIImagePickerController your View Controller class will also need to conform to the UINavigationControllerDelegate protocol. All of the methods in this protocol are also optional, so it can simply be added to the class declaration.
class ViewController: UIViewController, UIImagePickerControllerDelegate,
UINavigationControllerDelegate {
}
We can now launch the image picker, and see that the delegate methods are being called when we select an image, and when we cancel editing.
The image picker is no longer automatically dismissed though. To dismiss it explicitly, you can add the following to each of the delegate methods.
dismis(animated: true, completion: nil)
How will the View Controller get access to the image?
We need to implement the two ImagePickerControllerDelegate methods to get access to an image chosen from the Photo library or camera.
The imagePickerController(_:didFinishPickingMediaWithInfo:)
method is passed a dictionary as its second parameter. This dictionary contains UIImage
objects and is of type [String: Any]
.
Below are the possible dictionary keys for the original version of the selected image.
let UIImagePickerControllerMediaType: String
Specifies the media type selected by the user.
let UIImagePickerControllerOriginalImage: String
Specifies the original, uncropped image selected by the user.
let UIImagePickerControllerEditedImage: String
Specifies an image edited by the user.
let UIImagePickerControllerCropRect: String
Specifies the cropping rectangle that was applied to the original image.
let UIImagePickerControllerMediaURL: String
Specifies the filesystem URL for the movie.
let UIImagePickerControllerMediaMetadata: String
Metadata for a newly-captured photograph.
let UIImagePickerControllerLivePhoto: String
The Live Photo representation of the selected or captured photo.
The value in the info dictionary will be an optional type, and so it should be conditionally unwrapped. Here we use the conditional downcast operator as?
to cast the value to a UIImage
if let image = info[/* Dictionary Key Goes Here */] as? UIImage {
imagePickerView.image = image
}
The image is distorted to fit the screen
By default UIImageViews stretch images to fit into their bounds, in most cases you will probably want to keep the original aspect ratio of the image and center it within the UIImageView. Different behaviors can be specified by setting the “content mode” of the UIImageView in the attributes inspector.
Launching the Image Picker
To launch the camera and use a newly taken photo is almost identical to the code for picking an image from the album.
Setup an action method connected to the camera button just like the one for the album button, but this time adding the sourceType
.
@IBAction func pickAnImageFromCamera(_ sender: Any) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
present(imagePicker, animated: true, completion: nil)
}
Disabling the Camera Button
If the device being used doesn't have a camera the UIImagePickerController class has just the bool for the scenario isSourceTypeAvailable
.
We want to disable the camera button in cases when this bool returns false for the sourceType
. So we add the following to the viewWillAppear
.
cameraButton.isEnabled = UIImagePickerController.isSourceTypeAvailable(.camera)