Очень медленно загружать изображения из PHAsset - PullRequest
0 голосов
/ 04 сентября 2018

Я использую следующий код для извлечения изображений и AVAsset из PHAsset. Вот два массива в коде:

  1. galleryArr: для хранения изображений для просмотра коллекции.

  2. mutableDataArr: хранение изображений (для графических ресурсов) и видео (для AVAsset) для загрузки на сервер

Очень медленно получать все изображения из массива PHAssets. Я гуглил по этому поводу, большинство людей говорит удалить эту строку [options setSynchronous: YES]; но если я удаляю эту строку, то завершение вызывается дважды, и массив дублирует объекты (так как объекты добавляются в массив при завершении).

for (int i = 0; i < assets.count; i++) {

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
    options.resizeMode = PHImageRequestOptionsResizeModeExact;
    [options setNetworkAccessAllowed:YES];
    [options setSynchronous:YES];

    PHImageManager *manager = PHImageManager.defaultManager;

    PHVideoRequestOptions *videoOptions = [[PHVideoRequestOptions alloc] init];
    videoOptions.networkAccessAllowed = YES;
    __weak typeof(self) weakSelf = self;

    if (assets[i].mediaType == PHAssetMediaTypeVideo) {
        [manager requestAVAssetForVideo:[assets objectAtIndex:i] options:videoOptions resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
            if ([asset isKindOfClass:[AVURLAsset class]])
            {
                [weakSelf.mutableDataArr addObject:asset];
            }
        }];
    }

    [manager requestImageForAsset:[assets objectAtIndex:i]
                       targetSize: CGSizeMake(1024, 1024) //PHImageManagerMaximumSize
                      contentMode:PHImageContentModeAspectFit
                          options:options
                    resultHandler:^(UIImage *image, NSDictionary *info) {
                        if (image) {
                            dispatch_async(dispatch_get_main_queue(), ^{

                                if (assets[i].mediaType != PHAssetMediaTypeVideo) {
                                    [weakSelf.mutableDataArr addObject:image];
                                }
                                [galleryArr addObject:image];
                                if (i+1 == assets.count) {
                                    [SVProgressHUD dismiss];
                                    [weakSelf.galleryCollectionView reloadData];
                                }



                            });
                        }
                    }];
});


}

Любое предложение, пожалуйста?

1 Ответ

0 голосов
/ 04 сентября 2018

Только одна мысль, похоже, что вы загружаете все изображения из массива, прежде чем удалить свой прогресс HUD и отобразить галерею. Поскольку количество изображений может быть очень большим и предполагать, что вы используете представление коллекции или подобное, это довольно сложно, прежде чем что-либо отобразить.

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

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

Когда изображение возвращалось, ячейка добавляла его в кэш-память, а затем, если ячейка не использовалась повторно для другого изображения (из-за быстрой прокрутки), оно отображало изображение.

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

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

...