随时间检索PHAsset的性能

时间:2018-07-13 17:02:38

标签: swift performance phasset photokit phassetcollection

我目前正在将用户照片库构建到应用程序中。到目前为止,我只是在UICollectionView中列出了所有用户的照片。现在,我想将时刻群集添加为部分,类似于iOS Photos应用程序。

我在做什么(有点简化):

let momentClusters = PHCollectionList.fetchMomentLists(with: .momentListCluster, options: options)
momentClusters.enumerateObjects { (momentCluster, _, _) in
    let moments = PHAssetCollection.fetchMoments(inMomentList: momentCluster, options: nil)
    var assetFetchResults: [PHFetchResult<PHAsset>] = []
    moments.enumerateObjects { (moment, _, _) in
        let fetchResult = PHAsset.fetchAssets(in: moment, options: options)
        assetFetchResults.append(fetchResult)
    }
    //save assetFetchResults somewhere and use it in UICollectionView methods
}

事实证明,这比我以前花费了很多时间-最多需要一分钟,而我的iPhone X大约需要2秒(带有约1.5万张图片)。显然,这是不可接受的。

为什么提取时刻的性能这么差,我该如何改善呢?我使用的API错误吗?

我尝试按需加载资产,但是这很困难,因为那时我必须处理每时每刻的估计项目数,并在用户滚动时重新加载部分-我无法以这种方式工作令人满意(滚动流畅,没有明显的重新加载)。

有帮助吗?这个API应该如何运作?我用错了吗?

更新/零件解决方案

因此,在玩转之后,事实证明以下是问题的很大一部分: 我正在使用带有排序描述符的选项来获取资产:

let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
let assets = PHAsset.fetchAssets(in: moment, options: options)

似乎排序不允许PhotoKit在内部使用索引或缓存。删除sortDescriptors可以显着加快获取速度。它仍然比以前慢,并且需要更多提示,但是这使加载时间更容易承受。

请注意,如果没有排序描述符,则资产将首先返回最旧的资产,但是通过在cellForItemAt:中以相反的顺序检索资产,可以很容易地手动解决此问题(因此0,0的单元格将得到第一个时刻的最后资产)

1 个答案:

答案 0 :(得分:1)

免责声明:与性能相关的答案必定是推测性的...

您描述了两个极端:

  • 在显示收藏集之前先获取所有资产
  • 懒惰地获取所有资产,使用估计的数量并重新加载

但是有中间选项。例如,您一开始只能获取时刻,然后让每个时刻获取资产都受集合视图的驱动。但是,与其等到可见的一刻之前就获取它们的内容,不如使用UICollectionViewDataSourcePrefetching协议来决定要在 在屏幕上可见之前开始获取什么内容。