loading...
Cover image for Checking out the new PHPickerViewController in iOS 14

Checking out the new PHPickerViewController in iOS 14

nemecek_f profile image Filip Němeček Originally published at nemecek.be ・3 min read

In iOS 14 there is a brand new way to let users select a photo(s) or video(s) from their library to use in your app and it has some cool features and benefits. Let's see what these are and how basic PHPickerViewController usage looks like.

Benefits

No permissions required - you don't need to provide usage description in Info.plist to present the new picker and system does not show the allow access dialog. That is because users have full control over what media they select and subsequently send to your app.

Modern UI consistent with Photos - the new picker is much easier to use because the UI is very similar to what you get in Photos and there is also a search. This should be much better selection experience for the users than with the UIImagePickerViewController

Multi-selection - what else to say? 🙂

Usage overview

Using the new PHPickerViewController is pretty straightforward. It uses the traditional delegate model that will alert you when user finishes her selection. There is just a single delegate method to support and a bit of configuration.

Start by importing the PhotosUI framework:

import PhotosUI

Then continue with creating the configuration object PHPickerConfiguration. So far this allows to customize how many media files user can select and what kind of:

var configuration = PHPickerConfiguration()
configuration.selectionLimit = 3
configuration.filter = .images

In this example we are setting the selectionLimit to 3 (default is 1). You can also set 0 to mean unlimited. And next with filter we are saying that we want just images.

You can also ask for videos or livePhotos and combine these with the any(of: method like so:

configuration.filter = .any(of: [.livePhotos, .images])

Next create the picker itself and set yourself as its delegate:

let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self

We have two things left. Present the picker:

present(picker, animated: true, completion: nil)

The UI is different depending if multi-selection is enabled or not.

The new PHPhotoPickerViewController

And implement the delegate:

extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        dismiss(animated: true, completion: nil)
        guard !results.isEmpty else { return }
     }
}

So far we are just dismissing the picker and checking that we have results.
Unlike with UIImagePickerViewController we won't get the URL path to the file but instead a NSItemProvider that we can ask to load a specific object. For images this may look like this:

if provider.canLoadObject(ofClass: UIImage.self) {
     provider.loadObject(ofClass: UIImage.self) { (image, error) in
             DispatchQueue.main.async {
                 if let image = image as? UIImage {
                      self.imageView.image = image
                 }
             }
    }
 }

Just to be safe we first ask if the object can be loaded and then load it. To be honest I am not that well versed with NSItemProvider.

With UIImagePickerViewController there was a settings to specify the resolution for exported media which here does not appear to be a case. I plan to investigate this further and either update this post or write new one detailing how to get video or image with specific resolution.

In the WWDC 20 session about this new photo picker Apple specifically mentions that we should be using this new one instead of the older UIImagePickerViewController. This is not deprecated yet but presets for image/video quality are as per new documentation:

Posted on by:

nemecek_f profile

Filip Němeček

@nemecek_f

Primarily iOS developer, I also like Django and Python. And dabble with JavaScript occasionally. Love reading and coffee.

Discussion

markdown guide