Избегайте распаковки изображений, блокирующей основной поток

У меня есть код для отображения анимированного GIF-изображения с использованием UIImageView, здесь: https://github.com/amleszk/GifBlocking

Это работает хорошо в 99% случаев, хотя есть проблема с определенным типом изображения GIF. Пример можно найти здесь: http://i.imgur.com/mbImw.gif

Этот gif отлично принимает 101 изображение, а затем блокирует основной поток, когда приходит время отображать UIImageView, содержащий анимированные изображения. Можно распаковать gif, если он сжат, но как мне остановить блокировку основного потока?

В основном потоке вызываются следующие методы: DGifDecompressInput DGifDecompressLine copyImageBlockSetGIF

проблема в том, что распаковка gif происходит, когда представление добавляется в иерархию, что должно выполняться в основном потоке.

Спасибо


person amleszk    schedule 24.03.2013    source источник
comment
некоторый код, похожий на ..., довольно расплывчатый. Трудно помочь, не видя точного кода.   -  person Martin R    schedule 24.03.2013
comment
Добавлен репозиторий git для воспроизведения здесь: github.com/amleszk/GifBlocking   -  person amleszk    schedule 24.03.2013


Ответы (3)


Код grasGendarme полезен, но обратите внимание, что UIImage ленив и не будет декодировать изображение до тех пор, пока оно действительно не понадобится. Суть в том, что вам нужно принудительно распаковать фоновый поток, используя CGContextDrawImage. Поэтому используйте UIImage+JTImageDecode.h, чтобы создать несжатую версию изображения на фоне, а затем установите ее обратно. к основному потоку.

person Jano    schedule 24.03.2013
comment
Работает хорошо (недостаток в том, что изображение отображается дважды?), репозиторий git был обновлен с примером. - person amleszk; 25.03.2013
comment
Рендеринг означает создание изображения из форматированных данных. Здесь изображение визуализируется (распаковывается) один раз, затем сохраняется в объекте UIImage и позже выгружается в видеопамять. Независимо от того, делаете ли вы это в два этапа или в один, изображение будет отображаться только один раз. - person Jano; 25.03.2013
comment
Я попробовал это, и мой якобы анимированный UIimage больше не анимируется, он просто показывает первый кадр - что-нибудь еще, что я упускаю из виду? - person Dom Vinyard; 28.03.2013
comment
Это не будет работать с анимированными изображениями, поскольку рисуется один кадр. Используйте github.com/mayoff/uiimage-from-animated-gif, который уже извлекает (и распаковывает) изображения с помощью CGImageSourceCreateImageAtIndex. - person Jano; 28.03.2013

Было бы здорово увидеть реальный код. Без этого наша помощь ограничена.

Может быть, вы можете добавить строку:

[self performSelectorInBackground:@selector(yourBlockingMethod:) withObject:yourObject];

Или измените свою библиотеку, чтобы распаковать GIF в фоновом потоке, а затем использовать setNeedsDisplay в основном потоке.

person Ilea Cristian    schedule 24.03.2013

Вы можете сделать так, чтобы все происходило в отдельном потоке, используя Grand Central Dispatch и последовательные очереди:

// create the queue that will process your data:
dispatch_queue_t dataProcessQueue = dispatch_queue_create("data process queue", NULL); // the name is there for debugging purposes
    //dispatch to the newly created queue, and do not wait for it to complete
    dispatch_async(dataProcessQueue, ^{
        // load and decode gif
        // ...
        dispatch_async(dispatch_get_main_queue(), ^{
            // put gif in place (UI work always happen on the main queue)
            // ...
    });
});
person toasted_flakes    schedule 24.03.2013