Я пытаюсь повысить производительность моего приложения для iPhone с интенсивным использованием изображений, используя дисковый кеш изображений вместо передачи по сети. Я смоделировал свой кэш изображений после SDImageCache ( http://github.com/rs/SDWebImage/blob/master/SDImageCache.m ), и он почти такой же, но без асинхронного ввода / вывода кеша.
У меня есть несколько видов прокрутки и таблицы, которые загружают эти изображения асинхронно. Если изображение находится на диске, оно загружается из кеша изображений, в противном случае выполняется сетевой запрос, а последующий результат сохраняется в кеше.
Проблема I ' m сталкивается с тем, что, когда я прокручиваю представления прокрутки или представления таблиц, наблюдается заметная задержка при загрузке изображения с диска. В частности, анимация перехода от одной страницы к другой в режиме прокрутки имеет небольшое замирание в середине перехода.
Я попытался исправить это следующим образом:
Есть ли способ улучшить работу моего диска или уменьшить влияние на пользовательский интерфейс?
Обратите внимание, что я уже кэширую изображения в памяти. Итак, когда все загружено в память, пользовательский интерфейс становится приятным и отзывчивым. Но когда приложение запускается или отправляются предупреждения о нехватке памяти, я столкнусь со многими из этих задержек пользовательского интерфейса, поскольку изображения загружаются с диска.
Соответствующие фрагменты кода приведены ниже. Не думаю, что делаю что-то необычное или сумасшедшее. Задержка не кажется заметной на 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. Я предполагаю, что одним из улучшений было бы уменьшение размера изображений, загружаемых в представление прокрутки и представления таблиц, что, тем не менее, было тем, что я планировал сделать. Однако я просто не понимаю, как другие приложения, интенсивно использующие фотографии, могут без проблем с производительностью отображать фотографии в довольно высоком разрешении в прокручиваемых представлениях без проблем с производительностью при переходе на диск или по сети.