Проблема производительности AVAssetImageGenerator
Я пытаюсь создать видео галерею.
Для отображения видео я использую UICollectionView
, каждый UICollectionViewCell
имеет фон с миниатюрой видео. Для создания миниатюры видео я использую метод с логикой:
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0,15);
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime timeRequested, CGImageRef image, CMTime timeActual, AVAssetImageGeneratorResult result, NSError *error)
{
NSLog(@"handler^()");
if (result == AVAssetImageGeneratorSucceeded)
{
thumbnail = [UIImage imageWithCGImage: image];
success(thumbnail);
}
else
{
failure(error);
}
};
CGSize maximumSize = CGSizeMake(CLIPBOARD_COLLECTION_VIEW_CELL_WIDTH, CLIPBOARD_COLLECTION_VIEW_CELL_HEIGHT);
generator.maximumSize = maximumSize;
NSLog(@"generateCGImagesAsynchronouslyForTimes:");
[generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:time]] completionHandler:handler];
Я заметил что generateCGImagesAsynchronouslyForTimes
не работает полностью асинхронно. Между вызовами этого метода есть промежуток времени. Это вызывает большую задержку при загрузке ячеек табличного представления. Если я прокомментирую строку [generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:time]] completionHandler:handler]
тогда нет видимых лагов (ни изображений).
Как я могу решить эту проблему производительности?
2 ответа
AVAssetImageGeneratorCompletionHandler
блок не гарантированно вызывается в главном потоке:
Параллельное программирование с AV Foundation
Вызовы из AV Foundation - вызовы блоков, наблюдателей значения ключа и обработчиков уведомлений - не гарантированно выполняются в каком-либо конкретном потоке или очереди. Вместо этого AV Foundation вызывает эти обработчики в потоках или очередях, в которых он выполняет свои внутренние задачи. Вы несете ответственность за проверку соответствия потока или очереди, в которой вызывается обработчик, задачам, которые вы хотите выполнить. Если это не так (например, если вы хотите обновить пользовательский интерфейс, а выноска отсутствует в главном потоке), вы должны перенаправить выполнение ваших задач в безопасный поток или очередь, которые вы распознаете, или которые вы создаете для цель.
Звонит success
а также failure
с dispatch_async
исправить проблему?
dispatch_async(dispatch_get_main_queue(), ^{
if (success) {
success();
}
)};
Существует несколько способов перенаправить запрос асинхронной генерации изображения в другой поток, одним из которых является инкапсуляция функции в NSBlockOperation, добавленной в NSOperationQueue с базовой очередью, настроенной на то, что наиболее подходит для вашего приложения.
Наиболее подходящую очередь должно быть относительно легко угадать, если вы не знаете, так как там только несколько вариантов.