WWDC 20
Meet the new Photos picker
PHPicker: new system-provided picker screen that gives you access to photos and videos from the user’s photo library
New design and new easy to use API
It’s recommended that you use this picker instead of building your own custom photo selection UI
New version includes:
- an integrated search
- easy multi-select
- zoom gesture
PHPicker is private by default:
- the picker screen runs out of process and talks to the app via XPC
- your app has no direct access to the photos library
- it doesn’t need to get photo library permission (don’t ask for it unless you *really* need it)
- you only get selected photos and videos in response
PHPicker is not a name of a single class, but a set of classes that work together
Elements of the API
PHPickerConfiguration – lets you specify limits and filters:
selectionLimit– number of items that can be selected (1 by default, 0 = unlimited)filter– e.g..imagesor.any(of: [.videos, .livePhotos])
PHPickerViewController – the main VC handling the picker
- note: the picker doesn’t dismiss itself automatically, call
picker.dismiss(animated:)when you get the response
PHPickerViewControllerDelegate – delegate for the picker
picker(_: didFinishPicking results:)
PHPickerResult – an array of these objects is passed to the app in response
Displaying the picker:
let configuration = PHPickerConfiguration() // ... let picker = PHPickerViewController(configuration: configuration) picker.delegate = self present(picker, animated: true)
Handling the results:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
// get the first item provider from the results
let itemProvider = results.first?.itemProvider
if let itemProvider = itemProvider {
// access the UIImage representation for the result
if itemProvider.canLoadobject(ofClass: UIImage.self) {
itemProvider.loadobject(ofClass: UIImage.self) { image, error in
if let image = image {
// do something with the UIImage
}
}
}
}
}
If the user cancels the picker dialog, the delegate callback will still be called, with an empty results list
You don't need to load all returned images immediately when they are returned – you can just keep a reference to the item providers and load them later when they are needed
Getting asset identifiers:
You can normally extract picked photos from PHPickerResult item providers without touching the PHPhotoLibrary or PhotoKit at all, but if you do need to access the photo library anyway, then pass it to PHPickerConfiguration and get assetIdentifier references from the picker results:
let photoLibrary = PHPhotoLibrary.shared() let configuration = PHPickerConfiguration(photoLibrary: photoLibrary) // in PHPickerViewControllerDelegate callback: let identifiers: [String] = results.compactMap(\.assetIdentifier) let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
With limited library access:
If you use PHPicker with photo library access and you only got limited access to a subset of photos, then:
PHPickerwill still let the user choose photos from their whole library- but the selection you have direct access to will not be extended by what they choose in the picker
- to ask the user to extend the selection of assets available to your app, you need to use another API – more info in Handle the Limited Photos Library in Your App
Recommendations
The old AssetLibrary framework is deprecated, please switch to PhotoKit
The photo library APIs from UIImagePickerController are also deprecated now
It's really recommended to use the PHPicker API instead of building your own custom picker UI – it provides a consistent UI with other apps that the users are familiar with, and allows you to ask the user for a choice of photos without requiring Photo Library access
Seriously, do not ask for Photo Library access before showing the picker and do not require granting this access before showing the picker :)
If your app currently has access to the Photo Library and only uses it to pick selected photos, please reconsider if you can switch to PHPicker instead and not require Photo Library access