Эта проблема раздражала меня чуть более одного дня.Суть в том, что у меня есть настройка Grouped UITableView, так что в каждом разделе есть только одна запись.Каждая ячейка в табличном представлении содержит UIImageView, который занимает всю ширину и длину ячейки.Кроме того, каждая ячейка имеет заданную высоту и ширину.
Вот мой метод инициализации:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[[self layer] setMasksToBounds:NO];
[[self layer] setShouldRasterize:YES];
[[self layer] setRasterizationScale:[[UIScreen mainScreen] scale]];
[[self layer] setCornerRadius:10];
_bgCoverView = [[UIImageView alloc] initWithFrame:CGRectZero];
[_bgCoverView setClipsToBounds:YES];
[[_bgCoverView layer] setCornerRadius:10];
[_bgCoverView setContentMode:UIViewContentModeScaleAspectFill];
[self.contentView addSubview:_bgCoverView];
[_bgCoverView release];
//Init other parts of the cell, but they're not pertinent to the question
}
return self;
}
Это мои подпредставления макета:
- (void)layoutSubviews{
[super layoutSubviews];
if (!self.editing){
[_bgCoverView setFrame:CGRectMake(0, 0, tableViewCellWidth, self.contentView.frame.size.height)];
}
}
Этомой установщик для ячейки:
- (void)setGroup:(Group*)group{
//Set background cover for the contentView
NSSet *usableCovers = [[group memories] filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"pictureMedData != nil || pictureFullData != nil || (pictureMedUrl != nil && NOT pictureMedUrl contains[cd] '/missing.png')"]];
Memory *mem = [usableCovers anyObject];
[_bgCoverView setImage:[UIImage imageWithContentsOfFile:@"no_pics_yet.png"]];
if (mem != nil){
[Folio cacheImageAtStringURL:[mem pictureMedUrl] forManagedObject:mem withDataKey:@"pictureMedData" inDisplay:_bgCoverView];
}
}
Вот где я думаю, что я получаю динг производительности.Во-первых, это отфильтрованный набор вызовов.Если в наборе много объектов, это может замедлить работу.Однако объектов, как правило, относительно мало.Кроме того, когда я удалил эту строку кода, я не увидел никаких изменений в производительности, поэтому это маловероятно.
Итак, это в значительной степени оставляет мой метод кэширования (который находится в классе помощника).Вот метод:
+(void)cacheImageAtStringURL:(NSString *)urlString forManagedObject:(NSManagedObject*)managedObject withDataKey:(NSString*)dataKey inDisplay:(NSObject *)obj{
int objType = 0; //Assume UIButton
if (obj == nil)
objType = -1;
else if ([obj isKindOfClass:[UIImageView class]])
objType = 1; //Assign to UIImageView
NSData *data = (NSData*)[managedObject valueForKey:dataKey];
if ([data bytes]){
if (objType == 0) [(UIButton*)obj setBackgroundImage:[UIImage imageWithData:data] forState:UIControlStateNormal];
else if (objType == 1) [(UIImageView*)obj setImage:[UIImage imageWithData:data]];
return;
}
//Otherwise, do an ASIHTTPRequest and set the image when it's returned, save the data into core data so that we get a cache hit the next time.
}
Независимо от того, кэшируются ли изображения или нет, существуют серьезные проблемы с производительностью при прокрутке этого представления.Если я закомментирую метод кеширования, он работает довольно хорошо.Кроме того, другие представления, вызывающие этот метод, являются вялыми, поэтому я почти уверен, что это что-то здесь.
Однако я также скажу, что я также с подозрением отношусь к коду cornerRadius, однако я слышал, чтоесли вы установили значение yesRasterize на YES, это приведет к увеличению производительности.Тем не менее, я не уверен, что это на 100% верно или моя реализация выключена.
Любая помощь будет принята с благодарностью.
ОБНОВЛЕНИЕ
Пока еще не исправлено на 100%, но мы находимся там.
Эти переменные должны быть установлены по запросу:
[request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
Первая команда сообщает кэшу только пинговатьсервер для изображений, если они не кэшируются.Второй указывает кэшу постоянно хранить изображения в течение жизненного цикла приложения.
Это дало мне часть пути.Некоторые изображения загружались мгновенно, тогда как другие казались вялыми.Я провел дополнительные исследования и добавил в свой делегат приложения следующие строки кода:
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
Первая строка имеет решающее значение.Действие ASIHTTPRequest по умолчанию - следовать указаниям веб-сервера.Так что, если он скажет вам в своих заголовках не кэшировать ответ, он не будет.Эта строка переопределяет это.Теперь это отлично сработало на моем симуляторе iOS.Затем я попробовал его на своем 4S, и он снова был медленным.
Причина была в том, что я настроил блок кода в своем запросе, чтобы при успешном извлечении изображения я сохранял его в CoreДанные.Этот вызов вызывался каждый раз, даже для кэшированных запросов.
Это потому, что ASIHTTPRequest по-прежнему будет отправлять запрос независимо от того, использует ли он кэшированную копию ваших данных.Если у него есть кэшированная копия, он не будет отправлять запрос на сервер, а вместо этого заполняет данные ответа своего объекта запроса кэшированными данными.Поэтому после того, как мой блок позаботится о работе дисплея, я звоню:
if ([request didUseCachedResponse]) return;
Это очень хорошо работает на 4S и 4. Однако 3GS все еще катастрофически медленен: - (.
Это потому, что ASIHTTPRequest использует кэшированную копию моего NSData, а не моего UIImage. Поэтому ему нужно пересоздавать изображение каждый раз, когда он использует кэш. Это имеет смысл, потому что ASIHTTPRequest только возвращает данные и не знаетто, что вы собираетесь делать с данными впоследствии, так что он всегда будет вызывать ваш код, настроенный при возврате запроса.И поскольку мой блок кода преобразует изображение из данных, это то, что я получаю.
A WAY FORWARD
Я думаю, что для повышения быстродействия, который я хочу, необходимо реализовать пользовательский кэш UIImage. Если мы найдем файл в кеше, мы вернем объект UIImage. Еслинет, тогда мы создаем запрос и сохраняем его в кеше по возвращении.