Производительность для получения PHAssets с моментами

В настоящее время я создаю галерею пользовательских фотографий в приложении. Пока я просто перечислил все фотографии пользователя в 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
}

Оказывается, это НАМНОГО больше времени, чем то, что я делал раньше - до минуты по сравнению с примерно 2 секундами на моем iPhone X (с галереей около 15 тыс. Изображений). Очевидно, это недопустимо.

Почему производительность извлечения моментов так плоха, и как я могу улучшить ее? Я использую 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 ответ

Отказ от ответственности: Ответы, связанные с производительностью, обязательно являются умозрительными...

Вы описали две крайности:

  • Предварительная загрузка всех ресурсов на все моменты перед отображением коллекции
  • Получить все активы лениво, использовать расчетный счет и перезагрузить

Но есть промежуточные варианты. Например, вы можете сначала выбрать только моменты, а затем разрешить выбор ресурсов за момент в представлении сбора. Но вместо того, чтобы ждать появления видимых моментов, прежде чем извлекать их содержимое, используйте UICollectionViewDataSourcePrefetching протокол, чтобы решить, что начинать выборку до того, как эти элементы будут видны на экране.

Другие вопросы по тегам