[SWIFT] Get the selected image as Data with PHPickerViewController (and handle Live Photo)

New photo selection PHPickerViewController

Access rights to albums have been revised in iOS14. In iOS14, let's replace the application that performs photo selection using the conventional UIImagePicker with PHPickerViewController.

Benefits of using PHPickerViewController

If you just want to select a photo, you don't need to give the app photo access. That annoying permission selection dialog and goodbye at the first startup.

This is because PHPickerViewController runs in a separate process (separate from the host app), so photo access is done by PHPicker. From there, the app extension mechanism is used to pass the selected photo information to the host app, so access rights to the album are no longer required.

PHPickerViewController also supports multiple photo selection.

Purpose

Imagine you want to select a photo, get the file as is and send it to the backend, or save it in your app. Since loadObject is a UIImage, it is intended for people who are in trouble if the original meta information is lost.

environment

Xcode12 iOS14

Show photo selection


import PhotosUI

private func showPhpicker() {
    //If you want to get it as PHAsset later, specify the argument.
    var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
    //Number of simultaneous photo selections. Unlimited at 0
    config.selectionLimit = 1
    config.filter = PHPickerFilter.images

    let pickerViewController = PHPickerViewController(configuration: config)
    pickerViewController.delegate = self

    self.present(pickerViewController, animated: true, completion: nil)
}

Post-selection processing

Is it like the following? HEIC is extracting the JPEG stored inside. In the case of an image, get it with the loadDataRepresentation method.

I came up with a method to get the URL with loadItem and convert it to Data, but since the album can be accessed only on the process of PHPickerViewContrller, no matter how much the URL is known, the album via the URL from the application You cannot access the resources of.


///Method after selection
/// - Parameters:
///   - picker: PHPickerVIewController
///   - results:List of selection results
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    picker.dismiss(animated: true, completion: {
        // TODO:Processing after PHPickerView is closed
    })
    
    guard let provider = results.first?.itemProvider else { return }
    guard let typeIdentifer = provider.registeredTypeIdentifiers.first else { return }

    //Check if the identifier can be determined
    if provider.hasItemConformingToTypeIdentifier(typeIdentifer) {
        //Available as Live Photo
        if provider.canLoadObject(ofClass: PHLivePhoto.self) {
            //LivePhoto is loaded with LoadObject by specifying Class
            
            provider.loadObject(ofClass: PHLivePhoto.self) { (livePhotoObject, error) in
                do {
                    if let livePhoto:PHLivePhoto = livePhotoObject as? PHLivePhoto {
                        //Extract still images from Live Photo properties(HEIC format)
                        if let imageUrl = livePhoto.value(forKey: "imageURL") as? URL {
                        
                            //Generate Data from URL (can be obtained because it refers to the data in HEIC
                            let data:Data = try Data(contentsOf: imageUrl)
                            
                            
                            
                            //Generate a path and save the image
                            //data.write(to: URL)

                        }
                    }
                } catch {
                    
                }
                
            }
            
        } else if provider.canLoadObject(ofClass: UIImage.self) {
            //General image
            //In the case of an image, get it with UIImage or loadData with loadObject.
            //When getting the URL with loadItem, getting the UIImage or Data from the URL requires access authority to the album.
            provider.loadDataRepresentation(forTypeIdentifier: typeIdentifer) { (data, error) in
                if let imageData = data {
                    var ext = ""
                    switch typeIdentifer{
                    case "public.jpeg ":
                        ext = ".jpg "
                    case "public.png ":
                        ext = ".png "
                    default:
                        break
                    }
                    
                    //Save image
                    //data?.write(to: URL)
                        
                }
                
            }
        }

    }

}

The sample project is below. https://github.com/onizine/PHPickerGetDataSample

Recommended Posts

Get the selected image as Data with PHPickerViewController (and handle Live Photo)
[IOS14] How to get Data type image data directly from PHPickerViewController?