Reputation: 73
So, I found similar questions asked before but when I tried the same way as what I got, and it does not work as I expected, so what I'm trying to do is, I want to get PHAsset from PHPickerResult from PHPickerViewController.
so experimenting it using this source as my base code, and combined it with what I got from this.
also already add
"Privacy - Photo Library Usage Description"
to the info.plist
when i tried this.
The code look like this.
import UIKit
import PhotosUI
class ViewController: UIViewController {
@IBOutlet weak var myImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func buttonDidTap(_ sender: Any) {
var configuration = PHPickerConfiguration()
configuration.selectionLimit = 1
configuration.filter = .any(of: [.images, .videos])
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
self.present(picker, animated: true, completion: nil)
}
}
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
let identifiers = results.compactMap(\.assetIdentifier)
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
fetchResult.enumerateObjects { (asset, index, stop) -> Void in
PHImageManager.default().requestImage(for: asset,
targetSize: CGSize.init(width: 20, height: 20),
contentMode: PHImageContentMode.aspectFit,
options: nil) { (image: UIImage?, _: [AnyHashable : Any]?) in
self.myImageView.image = image
}
}
}
}
After I try to debug the code, I found out that the code inside fetchResult.enumerateObjects
was not called that's why I can't get the image.
Or maybe I got the wrong syntax? can someone help me?
Upvotes: 6
Views: 9189
Reputation: 37
You can use this custom class ImagePickerManager:
import Foundation
import UIKit
import PhotosUI
class ImagePickerManager: NSObject, PHPickerViewControllerDelegate, UINavigationControllerDelegate {
var picker: PHPickerViewController?
var pickImageCallback : ((UIImage) -> ())?
var viewController: UIViewController?
override init(){
super.init()
}
func pickSingleImage(_ viewController: UIViewController, _ callback: @escaping ((UIImage) -> ())) {
pickImageCallback = callback
self.viewController = viewController
var configuration = PHPickerConfiguration()
configuration.filter = .any(of: [.images, .livePhotos])
configuration.selectionLimit = 1
picker = PHPickerViewController(configuration: configuration)
picker?.delegate = self
viewController.present(picker!, animated: true, completion: nil)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true) {
let itemProviders = results.map(\.itemProvider)
for item in itemProviders {
if item.canLoadObject(ofClass: UIImage.self) {
item.loadObject(ofClass: UIImage.self) { (image, error) in
DispatchQueue.main.async {
if let image = image as? UIImage {
self.pickImageCallback!(image)
}
}
}
}
}
}
}
}
Usage:
In the view controller initialise a variable:
let imagePicker = ImagePickerManager()
On the button action paste this line
ImagePickerManager().pickSingleImage(self) { pickedImage in
self.myImageView.image = pickedImage
}
Upvotes: -1
Reputation: 37
matt might be saying right but one more thing that you can do is the following. In this way image will be directly shown in the UIImageView with the same configuration that you have done.
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true)
let itemProviders = results.map(\.itemProvider)
for item in itemProviders {
if item.canLoadObject(ofClass: UIImage.self) {
item.loadObject(ofClass: UIImage.self) { (image, error) in
DispatchQueue.main.async {
if let image = image as? UIImage {
self.myImageView.image = image
}
}
}
}
}
}
Upvotes: 0
Reputation: 535138
If you need an asset later, you have to initialize the configuration with the photo library. So this line is wrong:
var configuration = PHPickerConfiguration()
You want:
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
Upvotes: 14