简体   繁体   English

我如何从 PHPickerResult 获取 PHAsset? iOS 14

[英]How can i get PHAsset from PHPickerResult? iOS 14

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.所以,我发现之前问过类似的问题,但是当我尝试与我得到的相同的方式时,它并没有像我预期的那样工作,所以我想做的是,我想从 PHPickerViewController 的 PHPickerResult 获取 PHAsset。

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.当我尝试这个时,也已经将“隐私 - 照片库使用说明”添加到info.plist

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.在尝试调试代码后,我发现fetchResult.enumerateObjects中的代码没有被调用,这就是我无法获取图像的原因。

Or maybe I got the wrong syntax?或者我的语法有误? can someone help me?有人能帮我吗?

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())

matt might be saying right but one more thing that you can do is the following. matt 可能说得对,但您还可以做以下事情。 In this way image will be directly shown in the UIImageView with the same configuration that you have done.这样图像将直接显示在 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
                    }
                }
            }
        }
    }
}

You can use this custom class ImagePickerManager:您可以使用此自定义 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:在视图 controller 中初始化一个变量:

let imagePicker = ImagePickerManager()

On the button action paste this line在按钮操作上粘贴此行

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM