4

PHPickerViewController allows access to copies of photo library assets as well as returning PHAssets in the results. To get PHAssets instead of file copies, I do:

        let photolibrary = PHPhotoLibrary.shared()
        var configuration = PHPickerConfiguration(photoLibrary: photolibrary)
        configuration.filter = .videos
        configuration.selectionLimit = 0
        
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        self.present(picker, animated: true, completion: nil)

And then,

 //MARK:- PHPickerViewController delegate

@available(iOS 14, *)
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    
    picker.dismiss(animated: true) {
        let identifiers:[String] = results.compactMap(\.assetIdentifier)
        let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
        
        NSLog("\(identifiers), \(fetchResult)")
    }
    
}

But the problem is once the photo picker is dismissed, it prompts for Photo Library access which is confusing and since the user anyways implicitly gave access to the selected assets in PHPickerViewController, PHPhotoLibrary should load those assets directly. Is there anyway to avoid the Photo library permission?

Deepak Sharma
  • 5,577
  • 7
  • 55
  • 131

1 Answers1

4

Is there anyway to avoid the Photo library permission?

Yes, sort of:

  1. Change PHPickerConfiguration(photoLibrary: photolibrary) to PHPickerConfiguration()

  2. Do not use the assetIdentifier to return to the photo library (it will be nil anyway)

In that case, the user can give you image data but that's all. The picker is out-of-process and no data from the library itself is really coming across, just a mere image that the user has explicitly selected.

However, if your goal really is to return to the photo library and obtain the PHAsset, then you must have permission, as you now are indeed attempting to probe the photo library behind the scenes within your app.

What I do, when my app depends on PHAsset information, is to ask for photo library permission (if needed) before presenting the picker, and I don't present the picker if I can't get permission. So, the user taps a button, I discover we have no permission, I ask for permission, we get it (let's say), and I present the picker (doing the asynchronous dance, because the permission arrives asynchronously). Looks great.

By the way, this is also just as true with UIImagePickerController.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • This is what is the greatest paradox. For videos, it seems PHPickerViewController delivers a copy of the video which needs to be copied by the app, a waste of space! I thought once the user gave access to the photo via PHPickerViewController, it must be accessible to the app all the time! Besides this, the UI of PHPicker is super buggy in multi-select mode. Posting a separate question on it. – Deepak Sharma Oct 06 '20 at 18:51
  • "For videos, it seems PHPickerViewController delivers a copy of the video which needs to be copied by the app" But again, that was true also of UIImagePickerController. I really don't know what the big deal is here. If you want to call (say) `PHImageManager.default().requestPlayerItem(forVideo:)` so that you can play the video straight out of the photo library then yes, you need permission, and you always did need permission. – matt Oct 06 '20 at 18:58
  • 1
    Ok here my point is PHPickerViewController is the only VC that does not require Photo Library permission and assumes that the user has implicitly granted read access to the selected photos/videos. But then why request for permission when user accesses the same asset via PHAsset API? To me, this defeats the very purpose of implicit permission. – Deepak Sharma Oct 06 '20 at 19:03
  • 1
    Because the user has explicitly selected the image in the dialog. All the picker dialogs work this way. You don't need user permission to use the CNContactPickerViewController, for example. – matt Dec 23 '20 at 13:46
  • As of now at least, if you `PHPickerConfiguration(photoLibrary: .shared())`, it returns valid `assetIdentifier`s. – Jeshua Lacock May 08 '23 at 20:39