Принудительная загрузка изображений на iOS для предварительной загрузки

Я хочу предварительно загружать изображения, чтобы, когда я добавляю их UIImageView в свой currentView, PNG уже был в памяти, загружался, раздувался и т. Д.

Как видно из этого профилирования, изображения загружаются при отображении: введите здесь описание изображения

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

- (UIImageView*)createAnimationForReel:(NSString*)reel ofType:(NSString*)type usingFrames:(NSInteger)frames{
    UIImageView *imageView = [[UIImageView alloc] init];
    NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:frames];

    for (int i=0;i<frames;i++){
        NSString *image;
        if(i<10){
            image = [NSString stringWithFormat:@"%@_0%i", reel, i];
        } else {
            image = [NSString stringWithFormat:@"%@_%i", reel, i];
        }
        NSString *path = [[NSBundle mainBundle] pathForResource:image ofType:@"png" inDirectory:type];
        UIImage *anImage = [[UIImage alloc] initWithContentsOfFile:path];
        [imageArray addObject:anImage];
    }
    imageView.animationImages = [NSArray arrayWithArray:imageArray];
    imageView.animationDuration = 2.0;
    return imageView;
}

И когда я читаю документацию, там говорится: «Этот метод загружает данные изображения в память и помечает их как подлежащие очистке. Если данные очищаются и их необходимо перезагрузить, объект изображения снова загружает эти данные по указанному пути». говоря об initWithContentOfFile. Итак, мое изображение «должно» быть загружено.

Но нет.

Наверняка чего-то не хватает в моем отражении. Но что?


person Cyril Godefroy    schedule 10.02.2012    source источник


Ответы (3)


Можно было бы использовать фреймворк ImageIO (iOS 4.0+) и сделать что-то вроде этого:

NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:(id)kCGImageSourceShouldCache];

CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (CFDictionaryRef)dict);

UIImage* retImage = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CFRelease(source);
person Nyx0uf    schedule 10.02.2012
comment
Выглядит потрясающе и действительно загружает изображения, за исключением того, что они не кэшируются и все еще перезагружаются при отображении. Какой позор! Я начинаю думать, что это больше связано с тем, как работает UIImageView, а не с UIImage. - person Cyril Godefroy; 10.02.2012

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

- (void)preload:(UIImage *)image
{
    CGImageRef ref = image.CGImage;
    size_t width = CGImageGetWidth(ref);
    size_t height = CGImageGetHeight(ref);
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, space, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(space);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), ref);
    CGContextRelease(context);
}

Некрасиво, но это делает отрисовку изображения примерно в 4 раза быстрее. Я протестировал это с PNG размером 1 МБ 640 × 1136 на iPhone 4S:

  • Отрисовка его без предварительной загрузки занимает около 80 мс.
  • Предварительная загрузка заголовка изображения занимает около 10 мс, но впоследствии не ускоряет отрисовку.
  • Предварительная загрузка данных через поставщика данных занимает около 100 мс, но вряд ли впоследствии ускорит отрисовку.
  • Предварительная загрузка путем отрисовки, показанная в приведенном выше коде, занимает 100 мс, а следующая отрисовка — всего 20 мс.

Проверьте https://gist.github.com/3923434 для тестового кода.

person leo    schedule 20.10.2012
comment
Использование этого в фоновом потоке значительно улучшило производительность моего приложения, поскольку оно не блокировало основной поток для загрузки данных. Спасибо :) - person bendahmon; 11.03.2013
comment
Это потрясающее улучшение для рисования изображений - спасибо! Я получаю предупреждение о неявном преобразовании, хотя в отношении kCGImageAlphaPremultipliedFirst - person Jay Versluis; 23.11.2013
comment
Спасибо Джей за указание на предупреждение, теперь оно должно быть исправлено. - person leo; 28.11.2013
comment
должен был быть kCGBitmapAlphaInfoMask | kCGImageAlphaPremultipliedFirst. См. ioscodesnippet.com/2011/10/. 02/ - person Jeow Li Huan; 04.11.2014

Ответ Лео почти не дал мне прироста скорости загрузки. Эффект был заметен только тогда, когда я предварительно загружал одно изображение во второй раз сразу после первого. Например, если вы вызываете предварительную загрузку нажатием кнопки, первая предварительная загрузка дает прирост около 40 мс, если начальная загрузка составляет 200 мс. Это немного.

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

person Anton Plebanovich    schedule 19.06.2015