我目前正在将用户照片库构建到应用程序中。到目前为止,我只是在一个UICollectionView
. 现在我想将矩簇添加为部分,类似于 iOS 照片应用程序。
我在做什么(有点简化):
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 秒(有大约 15k 张图片的画廊)。显然,这是不可接受的。
为什么获取时刻的性能如此糟糕,我该如何改进它?我是否使用了错误的 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
将获得第一时刻的最后一个资产)