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.
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.
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.
Xcode12 iOS14
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)
}
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