【问题标题】:Performance for retrieving PHAssets with moments使用时刻检索 PHAsset 的性能
【发布时间】:2018-12-22 02:41:40
【问题描述】:

我目前正在将用户照片库构建到应用程序中。到目前为止,我只是在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 处的单元格将获得 最后 第一时刻的资产)

【问题讨论】:

    标签: swift performance phasset photokit phassetcollection


    【解决方案1】:

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

    你已经描述了两个极端:

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

    但也有介于两者之间的选项。例如,您可以一开始只获取时刻,然后让每个时刻获取资产由集合视图驱动。但是,不要等到时刻可见才获取其内容,而是使用UICollectionViewDataSourcePrefetching 协议来决定在这些项目应该在屏幕上可见之前开始获取什么。

    【讨论】:

    • 谢谢。我实际上并不了解该协议,我将尝试使用它来改进集合视图的行为:-) 但是,在这种特殊情况下,很大一部分痛苦是需要做很多工作才能找出如何每个部分都有很多项目(= 时刻),我认为 DataSourcePrefetching 在那里没有多大帮助:/
    • 您仍然需要估计部分计数并使用数据源预取来更新部分,但是: 1. 您至少可以在部分不在屏幕时更新您的 items-in-section-count(当你得到一个prefetchItemsAt 调用引用你尚未加载的部分,这是你获取它的信号)。 2. 使用 UICollection 添加/删除/更新项目方法而不是重新加载部分,您可能可以获得更流畅的更新。
    • 不幸的是,我无法让它在实践中可靠地工作。在 Apple 的文档中提到,prefetchItemsAt 可能不会为进入视野的每个索引路径调用。事实上,如果我快速滚动浏览集合视图,我会在某个时候遇到屏幕上出现的未预先设置的部分,这可能会由于估计计数大于实际计数而导致崩溃。跨度>
    • 用我想出的部分解决方案更新了问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多