PHAsset fetch 将 50% 的集合返回为 nil

Posted

技术标签:

【中文标题】PHAsset fetch 将 50% 的集合返回为 nil【英文标题】:PHAsset fetch returns 50% of the collection as nil 【发布时间】:2015-10-06 03:19:51 【问题描述】:

当我将PHAssetCollection 交给PHAsset.fetchAssetsInAssetCollection:options 时,我得到了PHAssets 的集合。对于返回给我的每个UIImage,也会返回一个 nil 值。

以下是我的cellForItemAtIndexPath:indexPath方法。

public override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("AssetCellIdentifier", forIndexPath: indexPath) as? AssetCollectionViewCell;

    let asset = self.assetFetchResult!.objectAtIndex(indexPath.row);
    self.imageManager.requestImageForAsset(
        asset as! PHAsset,
        targetSize: CGSize.init(width: asset.pixelWidth, height: asset.pixelHeight),
        contentMode: PHImageContentMode.AspectFill,
        options: nil)  (image, info) -> Void in
            print (image);
            if (image == nil) 
                return;
            


            cell?.assetThumbnail.contentMode = UIViewContentMode.ScaleAspectFit;
            cell?.assetThumbnail.image = image;
    

    return cell!;

如果我不放零检查

if (image == nil) 
    return;

然后 UICollectionView 什么也不渲染。一旦我添加了 nil 检查,集合视图就会开始渲染照片库资产集合中的图像。

为什么返回给我的 nil 数量总是与 UIImage 对象数量相同?我的请求中有什么东西我搞砸了吗?

这是我上面的print 调用的输出。

Optional(<UIImage: 0x12f8263d0>, 40, 30)
Optional(<UIImage: 0x12e5265a0>, 40, 30)
Optional(<UIImage: 0x12e664c90>, 40, 30)
Optional(<UIImage: 0x12e74c860>, 40, 30)
Optional(<UIImage: 0x12e58c580>, 40, 30)
Optional(<UIImage: 0x12e60b6f0>, 40, 30)
Optional(<UIImage: 0x12e7657d0>, 40, 30)
Optional(<UIImage: 0x12e6655e0>, 40, 30)
Optional(<UIImage: 0x12e743ca0>, 40, 30)
Optional(<UIImage: 0x12e5fb6e0>, 40, 30)
Optional(<UIImage: 0x12e5fb8e0>, 40, 30)
Optional(<UIImage: 0x12f85f3b0>, 40, 30)
nil
nil
nil
nil
nil
nil
nil
nil
nil
nil
nil
nil

更新:

这似乎发生在我返回的每个 PHAssetCollection 中。

更新 2:

这是我试图复制的 WWDC 示例中的部分内容。我确实注意到它确实的一件事,但我不是,它是标记单元格,以防止在重复使用时覆盖它。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

    AAPLGridViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellReuseIdentifier forIndexPath:indexPath];

    // Increment the cell's tag
    NSInteger currentTag = cell.tag + 1;
    cell.tag = currentTag;

    PHAsset *asset = self.assetsFetchResults[indexPath.item];
    [self.imageManager requestImageForAsset:asset
                                 targetSize:AssetGridThumbnailSize
                                contentMode:PHImageContentModeAspectFill
                                    options:nil
                              resultHandler:^(UIImage *result, NSDictionary *info) 

        // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used.
        if (cell.tag == currentTag) 
            cell.thumbnailImage = result;
        

    ];

    return cell;

【问题讨论】:

【参考方案1】:

您不能像在cellForItemAtIndexPath 中间调用它那样调用self.imageManager.requestImageForAsset。此方法cellForItemAtIndexPath 立即返回。同时,requestImageForAsset异步的 - 这意味着您的完成处理程序被调用稍后。到它被调用时,我们已经转移到另一个单元格;请记住,细胞被重复使用。所以你的整个方法都是荒谬的。

查看 Apple 的示例代码,了解如何使用图像管理器的缓存版本填充集合视图的单元格。

另外,我注意到您忽略了 PHImageRequestOptions。这很重要。你应该仔细考虑你想要什么。如果您没有设置任何值,这意味着您将面临完成处理程序将被多次调用的风险,当我们不再处于填充此单元格的过程中时,这又是没有意义的。

【讨论】:

我会看看的。我通过观看 WWDC 会议的理解是它已被处理,开发人员不必担心它,除非他们想要过滤给定的内容。如果没有选项,则返回所有内容。我还认为这是 50/50 很奇怪。对于每张图片,都有一个对应的 nil。如果只有照片云是原因,我不认为每张专辑都有 50% 的不可用。 你会如何推荐它?我或多或少只是复制 Apple 在他们的 WWDC 示例中发布的代码。我不认为我想抓取资产集合中的每张图像,如果用户从不滚动,这似乎是对带宽和内存的巨大使用。我知道我可以分批管理它; PHImageManager 应该为我处理这个问题,尽管听苹果的谈话。所以我对采取什么更好的方法有点困惑:/ 我明白你在说什么。在我从imageManager 的回调完成之前,可以重复使用该单元格。 我不是在“开车”。我在喊它! :) 那么您的图像管理器已经是缓存图像管理器了吗?因为在 Apple 示例中就是这样。

以上是关于PHAsset fetch 将 50% 的集合返回为 nil的主要内容,如果未能解决你的问题,请参考以下文章

将 PHAsset 转换为 UIImage 并将其显示给用户

有时 PHAsset fetchAssetsWithLocalIdentifiers:options 方法返回一个空的提取结果

从 PHAsset 中提取元数据返回意外的 nil 值

使用 PHImageManager 时,PHAsset 返回 UIImage 的 nil 值

为啥 PHAsset fetchAssetsWithOptions 不返回所有资产?

在 Nativescript 应用程序中将 PHAsset/AVAsset 转换为 mp4 视频