Как я могу получить PHAsset из PHPickerResult? iOS 14

Итак, я нашел похожие вопросы, которые задавали раньше, но когда я попробовал тот же способ, что и получил, и он не работает так, как я ожидал, поэтому я пытаюсь получить PHAsset из PHPickerResult из PHPickerViewController.

поэтому поэкспериментировал, используя этот источник в качестве базового кода, и объединил его с тем, что я получил из этого.

также уже добавили "Конфиденциальность - Описание использования библиотеки фотографий" в info.plist когда я попробовал это.

Код выглядит так.


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
            }
       }
    }
}

После того, как я попытался отладить код, я обнаружил, что код внутри fetchResult.enumerateObjects не позвонили, поэтому я не могу получить изображение.

А может я ошибся синтаксисом? Кто-нибудь может мне помочь?

3 ответа

Если позже вам понадобится актив, вы должны инициализировать конфигурацию с помощью библиотеки фотографий. Итак, эта строка неверна:

var configuration = PHPickerConfiguration()

Вы хотите:

var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())

Мэтт может быть прав, но еще одна вещь, которую вы можете сделать, это следующее. Таким образом, изображение будет отображаться непосредственно в UIImageView с той же конфигурацией, которую вы сделали.

      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
                    }
                }
            }
        }
    }
}

Вы можете использовать этот пользовательский класс 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)
                        }
                    }
                }
            }
        }
    }
  }
}

Применение:

В контроллере представления инициализируйте переменную:

      let imagePicker = ImagePickerManager()

В действие кнопки вставьте эту строку

      ImagePickerManager().pickSingleImage(self) { pickedImage in
        self.myImageView.image = pickedImage
    }
Другие вопросы по тегам