如何正确使用带有本地标识符的获取资产?

Posted

技术标签:

【中文标题】如何正确使用带有本地标识符的获取资产?【英文标题】:How do I correctly use fetch assets with a local identifier? 【发布时间】:2020-10-28 17:10:30 【问题描述】:

我试图弄清楚如何获取标识符数组并将它们以编程方式放入集合视图中。如果我错了,请纠正我,但我相信最好的方法是使用PHAsset.fetchAssets。我最多预计用户会获取 10 张图片(平均 3-4 张),所以我认为这个过程不会占用大量资源。我正在使用特定的标识符数组测试下面的代码。在我分配资产的行上的 cellForItemAt 函数中,我收到一条错误消息。请参阅该行上方的评论。我在 SO 上看到过类似的问题,但我无法应用我发现的任何内容。我做错了什么?

var identifier: [String] = ["83BDF9C0-E1FB-4F68-9F2C-99649A67E218/L0/001", "18D08CEC-4075-4488-BFD1-E9403B214356/L0/001", "74257416-6D9C-48B2-9CE0-C23B56CB4171/L0/001", "2EA7CACE-9B9B-4FC9-ABC5-03BCE2BDAA2A/L0/001", "46A4CD2B-4FEB-4BBE-86DC-B79ED49BC300/L0/001", "E4290EB0-2B16-46AE-9B98-83379F6128F3/L0/001", "7C0B36FF-320D-4083-92E4-5A1F464FFFB1/L0/001", "DEE1414C-2B92-4147-8C3C-A1775FB324AD/L0/001"]
    
class DetailViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
    
    var myCollectionView: UICollectionView!
    let imgManager = PHImageManager.default()
    let requestOptions = PHImageRequestOptions()
    var fetchResult: PHFetchResult<PHAsset>!
    
    override func viewDidLoad() 
        requestOptions.isSynchronous = false
        requestOptions.deliveryMode = .opportunistic
        let layout = UICollectionViewFlowLayout()
        myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        myCollectionView.delegate = self
        myCollectionView.dataSource = self
        myCollectionView.backgroundColor = UIColor.white
        myCollectionView.allowsMultipleSelection = true
        myCollectionView.register(ImageEditCell.self, forCellWithReuseIdentifier: "Cell")
        myCollectionView.showsVerticalScrollIndicator = false
        self.view.addSubview(myCollectionView)
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageEditCell
        cell.representedAssetIdentifier = identifier[0]
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        
        // LINE BELOW PRODUCES ERROR: Cannot convert value of type '[String]' to expected element type 'Array<String>.ArrayLiteralElement' (aka 'String')
        let asset = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: .none).firstObject
        
        imgManager.requestImage(for: asset!, targetSize: CGSize(width:120, height: 120),
                                contentMode: .aspectFill,
                                options: requestOptions,
                                resultHandler:  result, info in
                                    if cell.representedAssetIdentifier == self.identifier 
                                        cell.imageview.image = result
                                    
                                )
    

【问题讨论】:

【参考方案1】:

在这里,我已将 fetch 函数移至 viewDidLoad 以防止其他错误,而且我不确定您要获取的内容是否是带有图像的数组(如果是这样,那么通过放置 .firstObject 您正在获取单个图像可能会导致错误)

var identifier: [String] = ["83BDF9C0-E1FB-4F68-9F2C-99649A67E218/L0/001", "18D08CEC-4075-4488-BFD1-E9403B214356/L0/001", "74257416-6D9C-48B2-9CE0-C23B56CB4171/L0/001", "2EA7CACE-9B9B-4FC9-ABC5-03BCE2BDAA2A/L0/001", "46A4CD2B-4FEB-4BBE-86DC-B79ED49BC300/L0/001", "E4290EB0-2B16-46AE-9B98-83379F6128F3/L0/001", "7C0B36FF-320D-4083-92E4-5A1F464FFFB1/L0/001", "DEE1414C-2B92-4147-8C3C-A1775FB324AD/L0/001"]
    
class DetailViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
    
    var myCollectionView: UICollectionView!
    let imgManager = PHImageManager.default()
    let requestOptions = PHImageRequestOptions()
    var fetchResult: PHFetchResult<PHAsset>!
    
    override func viewDidLoad() 
       
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        let layout = UICollectionViewFlowLayout()
        myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        myCollectionView.delegate = self
        myCollectionView.dataSource = self
        myCollectionView.backgroundColor = UIColor.white
        myCollectionView.allowsMultipleSelection = true
        myCollectionView.register(ImageEditCell.self, forCellWithReuseIdentifier: "Cell")
        myCollectionView.showsVerticalScrollIndicator = false
        self.view.addSubview(myCollectionView)
let asset = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: .none)

    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageEditCell
        cell.representedAssetIdentifier = identifier[indexPath.row]
       
        imgManager.requestImage(for: asset!, targetSize: CGSize(width:120, height: 120),
                                contentMode: .aspectFill,
                                options: requestOptions,
                                resultHandler:  result, info in
                                    if cell.representedAssetIdentifier == self.identifier 
                                        cell.imageview.image = result
                                    
                                )
    

【讨论】:

欢迎来到 SO!我想我理解你的建议,但也许你可以提供一个例子。只需将我的代码复制到答案框中并按照您的建议进行编辑,因为您回避这更多的是评论而不是答案。 我已经编辑了我的答案,请检查它,如果它解决了问题,请告诉我【参考方案2】:

我终于明白了。我意识到我没有正确地将标识符转换为 UIImage,所以即使我已经修复了 OP 中的错误,它仍然无法工作,因为许多其他人会提出该解决方案。以下是我必须工作的解决方案:

    var myCollectionView: UICollectionView!
    var imageViews = [UIImageView]()
    var identifier = [
        "83BDF9C0-E1FB-4F68-9F2C-99649A67E218/L0/001",
        "18D08CEC-4075-4488-BFD1-E9403B214356/L0/001",
        "74257416-6D9C-48B2-9CE0-C23B56CB4171/L0/001",
        "2EA7CACE-9B9B-4FC9-ABC5-03BCE2BDAA2A/L0/001",
        "46A4CD2B-4FEB-4BBE-86DC-B79ED49BC300/L0/001",
        "E4290EB0-2B16-46AE-9B98-83379F6128F3/L0/001",
        "7C0B36FF-320D-4083-92E4-5A1F464FFFB1/L0/001",
        "DEE1414C-2B92-4147-8C3C-A1775FB324AD/L0/001"
    ]
    
    override func viewDidLoad() 
        let layout = UICollectionViewFlowLayout()
        myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        myCollectionView.delegate = self
        myCollectionView.dataSource = self
        myCollectionView.backgroundColor = UIColor.white
        myCollectionView.allowsMultipleSelection = true
        myCollectionView.showsVerticalScrollIndicator = false
        myCollectionView.register(CollectionCell.self, forCellWithReuseIdentifier: "Cell")
        self.view.addSubview(myCollectionView)
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return identifier.count
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionCell
        
        let options = PHFetchOptions()
        let results = PHAsset.fetchAssets(withLocalIdentifiers: identifier, options: options)
        let manager = PHImageManager.default()
        results.enumerateObjects  (thisAsset, _, _) in
            manager.requestImage(for: thisAsset, targetSize: CGSize(width: 200.0, height: 200.0), contentMode: .aspectFit, options: nil, resultHandler: (thisImage, _) in
                self.imageViews.append(UIImageView(image: thisImage))
            )
        
        let image = imageViews[indexPath.item]
        cell.imageView.image = image.image
        return cell
    

【讨论】:

以上是关于如何正确使用带有本地标识符的获取资产?的主要内容,如果未能解决你的问题,请参考以下文章

我正在尝试从本地标识符中获取资产并在 collectionview 中显示图像,但它会导致滚动抖动

在不加载 PHAsset us 照片库的情况下获取所有图像本地标识符/文件路径

使用照片框架获取带有本地标识符的相册

PHAsset Null 但本地标识符有效

如何在 IOS 中查找照片资产的标识符

带有不正确广告标识符 [IDFA] 使用的“无效二进制文件”