Вопрос по performance, uitableview, uiimage, uiimageview – Пользовательский UITableViewCell с большим UIImageView вызывает задержку прокрутки

10

У меня есть пользовательский UITableViewCell, который состоит из UIImageView и UILabel. Ячейка размером 320x104 пикселей, и imageView занимает всю область с надписью впереди. Всего 8 ячеек.

в ViewDidLoad я заранее создаю все необходимые изображения и кэширую их в словаре с правильными размерами.

Когда я прокручиваю UITableView, происходит заметная задержка каждый раз, когда встречается новая ячейка. Это не имеет смысла для меня, так как изображение, которое он использует, уже создано и кэшировано. Все, что я запрашиваю у ячейки, это ее UIImageView для визуализации изображения.

Я использую пользовательскую ячейку с ее представлением в xib и настраиваю свой UITableView для использования с:

[self.tableView registerNib: [UINib nibWithNibName: @ & quot; ActsCell & quot; расслоение: ноль]               forCellReuseIdentifier: myIdentifier];

Создание и настройка ячейки:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{  
    NSString* reuseIdentifier = @"ActsCell";
    ActsCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    // Configure the cell...
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

- (void)configureCell:(ActsCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{
    Act* act = [self.acts objectAtIndex:indexPath.row];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.title.text = act.name;
    cell.imageView.image = [self.imageCache objectForKey:act.uid];
}

Что может быть причиной задержки? Казалось бы, бесполезно пытаться что-то сделать Async, так как вся трудоемкая работа выполнена.

@Lvsti Можете ли вы рассказать о том, как я неправильно настраиваю reuseIdentifier? Undistraction
Если вы имеете в виду, что я не использую if (cell == nil) {// Create cell}, это не требуется при использовании registerNib: forCellReuseIdentifier: поскольку создание ячейки откладывается до VC. Undistraction
вы правы, это, вероятно, не так, иначе вы не получите никаких клеток обратно при снятии очереди ... Lvsti
да, я понял это. Что касается изображений, какого они размера? Lvsti
Я могу думать о двух вещах. Одним из них является то, что снятие очереди не выполняется, потому что вы не устанавливаетеreusableIdentifier должным образом. Другой размер изображения. Даже если изображения загружены, CG необходимо обработать данные изображения перед его отображением, что может включать в себя дорогостоящие операции, такие как масштабирование, компоновка и т. Д. Lvsti

Ваш Ответ

1   ответ
31

Используя инструменты, я обнаружил, что вUIImage - данные реального изображения распаковывались из PNG только на этапе рендеринга в основном потоке, что вызывало задержку при прокрутке.

Итак, после загрузкиUIImage с-initWithContentsOfFile: метод, я добавил код для рендеринга содержимого этого изображения в неэкранный контекст, сохранил этот контекст как новыйUIImage и использовал его дляUIImageView вUITableViewCellЭто сделало прокрутку снова гладкой и приятной для глаз.

В случае ссылки используется простой код, который я использую для принудительного считывания содержимого изображения в отдельном потоке (используя ARC):

UIImage *productImage = [[UIImage alloc] initWithContentsOfFile:path];

CGSize imageSize = productImage.size;
UIGraphicsBeginImageContext(imageSize);
[productImage drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
productImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

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

РЕДАКТИРОВАТЬ: документы дляUIGraphicsGetImageFromCurrentImageContext() скажем, что его следует использовать только из основного потока, но поиск в сети или SO показывает, что начиная с iOS 4UIGraphics.. методы стали потокобезопасными.

Приведенный выше код не предназначен дляcellForRowAtIndexPath, Любой сценарий плавной прокрутки ячеек с большим количеством данных (в данном случае изображений) - это перемещение самой тяжелой части загрузки в отдельный поток. И этот код предназначен для параллельного рабочего потока, он будет следить за тем, чтобы изображение загружалось в рабочий поток, а не в основной поток пользовательского интерфейса. ---- Но вы должны сначала научиться загружать изображения для ячеек табличного представления в отдельном потоке, это другая тема.
Это работа для меня, гораздо более гладкая после сохранения UIImage вместо загруженных данных, а затем преобразовывать в UIImage каждый раз, когда он будет использоваться. Спасибо большое.
Долго искал медленную / нестабильную причину. Вы сэр герой
Извините за поднятие и старый поток, но у меня похожая проблема, но я не могу понять, как / где использовать вышеуказанный код в cellForRowAtIndexPath
Это было абсолютно бесценно для меня. Я страдал от прерывистой прокрутки на UICollectionView с UIImageViews в каждой ячейке для отображения фотографии. Я старалсяa lot различных решений, но единственный способ приблизиться к 60FPS был чрезвычайно хакерским. Большинство решений, которые я пробовал, включали в себя предварительную загрузку NSCache UIImages с использованием imageWithContentsOfFile, но все, что я делал, всегда было небольшим скачком, поскольку новые ячейки появлялись на экране, пока я не реализовал ваш код выше. Как вы говорите, в imageWithContentsOfFile должен быть встроен какой-то ленивый механизм загрузки, который не упоминается в документации.

Похожие вопросы