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

Я пытаюсь повысить производительность моего приложения для iPhone с интенсивным использованием изображений, используя дисковый кеш изображений вместо передачи по сети. Я смоделировал свой кэш изображений после SDImageCache ( http://github.com/rs/SDWebImage/blob/master/SDImageCache.m ), и он почти такой же, но без асинхронного ввода / вывода кеша.

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

Проблема I ' m сталкивается с тем, что, когда я прокручиваю представления прокрутки или представления таблиц, наблюдается заметная задержка при загрузке изображения с диска. В частности, анимация перехода от одной страницы к другой в режиме прокрутки имеет небольшое замирание в середине перехода.

Я попытался исправить это следующим образом:

  • Использование объектов NSOperationQueue и NSInvocationOperation для создания запросы доступа к диску (таким же образом, как и SDImageCache), но это совсем не помогает с задержкой.
  • Настройка кода контроллера представления прокрутки так, чтобы он загружал изображения только тогда, когда представление прокрутки больше не прокручивается. Это означает, что доступ к диску срабатывает только тогда, когда просмотр прокрутки перестает прокручиваться, но если я немедленно попытаюсь перейти на следующую страницу, я могу заметить задержку при загрузке изображения с диска.

Есть ли способ улучшить работу моего диска или уменьшить влияние на пользовательский интерфейс?

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

Соответствующие фрагменты кода приведены ниже. Не думаю, что делаю что-то необычное или сумасшедшее. Задержка не кажется заметной на iPhone 3G, но довольно очевидна на iPod Touch 2-го поколения.

Код кэширования изображений:

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

- (BOOL)hasImageDataForURL:(NSString *)url {
    return [[NSFileManager defaultManager] fileExistsAtPath:[self cacheFilePathForURL:url]];
}

- (NSData *)imageDataForURL:(NSString *)url {
    NSString *filePath = [self cacheFilePathForURL:url];

    // Set file last modification date to help enforce LRU caching policy
    NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
    [attributes setObject:[NSDate date] forKey:NSFileModificationDate];
    [[NSFileManager defaultManager] setAttributes:attributes ofItemAtPath:filePath error:NULL];

    return [NSData dataWithContentsOfFile:filePath];
}

- (void)storeImageData:(NSData *)data forURL:(NSString *)url {
    [[NSFileManager defaultManager] createFileAtPath:[self cacheFilePathForURL:url] contents:data attributes:nil];
}

Код контроллера представления прокрутки

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

- (void)scrollViewDidScroll:(UIScrollView *)theScrollView {
    CGFloat pageWidth = theScrollView.frame.size.width;
    NSUInteger index = floor((theScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;

    [self loadImageFor:[NSNumber numberWithInt:index]];
    [self loadImageFor:[NSNumber numberWithInt:index + 1]];
    [self loadImageFor:[NSNumber numberWithInt:index - 1]];
}

- (void)loadImageFor:(NSNumber *)index {
    if ([index intValue] < 0 || [index intValue] >= [self.photoData count]) {
        return;
    }

    // ... initialize an image loader object that accesses the disk image cache or makes a network request

    UIView *iew = [self.views objectForKey:index];    
    UIImageView *imageView = (UIImageView *) [view viewWithTag:kImageViewTag];
    if (imageView.image == nil) {
        NSDictionary *photo = [self.photoData objectAtIndex:[index intValue]];
        [loader loadImage:[photo objectForKey:@"url"]];
    }
}

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

- (void)imageLoadedFor:(NSNumber *)index image:(UIImage *)image {
    // Cache image in memory
    // ...

    UIView *view = [self.views objectForKey:index];
    UIImageView *imageView = (UIImageView *) [view viewWithTag:kImageViewTag];
    imageView.contentMode = UIViewContentModeScaleAspectFill;
    imageView.image = image;
}

UPDATE

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

Задержка, похоже, слишком велика. быть просто более заметным при использовании дискового кеша, поскольку отставание всегда происходит прямо при переходе страницы. Возможно, я делаю что-то не так при назначении загруженного изображения соответствующему UIImageView?

Также - я пробовал использовать маленькие изображения (миниатюры 50x50), и задержка, похоже, улучшилась. Таким образом, похоже, что снижение производительности связано либо с загрузкой большого изображения с диска, либо с загрузкой большого изображения в объект UIImage. Я предполагаю, что одним из улучшений было бы уменьшение размера изображений, загружаемых в представление прокрутки и представления таблиц, что, тем не менее, было тем, что я планировал сделать. Однако я просто не понимаю, как другие приложения, интенсивно использующие фотографии, могут без проблем с производительностью отображать фотографии в довольно высоком разрешении в прокручиваемых представлениях без проблем с производительностью при переходе на диск или по сети.

6
задан pmc255 21 September 2010 в 08:54
поделиться