我如何从 PHPickerResult 获取 PHAsset? iOS 14

How can i get PHAsset from PHPickerResult? iOS 14

所以,我发现之前问过类似的问题,但是当我尝试与我得到的相同的方式时,它并没有像我预期的那样工作,所以我想做的是,我想从来自 PHPickerViewController 的 PHPickerResult。

所以用这个 source as my base code, and combined it with what I got from this 进行试验。

也已经添加 《隐私-图片库使用说明》 当我尝试这个时 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里面的代码没有被调用,所以无法获取图像。

或者我的语法有误?有人可以帮助我吗?

如果您稍后需要资产,则必须使用照片库初始化配置。所以这一行是错误的:

var configuration = PHPickerConfiguration()

你想要:

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

matt 可能说得对,但您还可以做以下事情。这样,图片将直接显示在 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
                    }
                }
            }
        }
    }
}

您可以使用这个自定义 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)
                        }
                    }
                }
            }
        }
    }
  }
}

用法:

在视图控制器中初始化一个变量:

let imagePicker = ImagePickerManager()

在按钮操作上粘贴此行

ImagePickerManager().pickSingleImage(self) { pickedImage in
        self.myImageView.image = pickedImage
    }