Кэшируемая производительность извлечения UIImages в UITableView - PullRequest
2 голосов
/ 10 августа 2010

Я уже некоторое время пользуюсь @ atebits's ABTableViewCell .Для тех, кто не знаком с ним, в основном он делает прокрутку табличного представления намного быстрее, рисуя все метки и изображения, вместо выделения объектов UIKit (таких как UILabels, UIImageView и т. Д.).

Теперь у меня есть довольно большое UITableViews, и в каждой ячейке есть маленькое (32x32) пользовательское изображение и средняя (75x75) миниатюра фотографии.Рисование действительно помогает ускорить прокрутку таблицы, но я все еще пытаюсь понять, как лучше всего получить эти изображения, которые должны быть нарисованы внутри ячеек.

Я смотрел на Apple LazyTableView пример, но я все еще не уверен, каков наилучший способ сделать это.Все, что я знаю, это то, что чем меньше кода / выделения у вас в cellForRowAtIndexPath:, тем лучше.

Поэтому мои изображения либо загружаются с сервера, либо извлекаются из моего CoreDataHelper.Мой вопрос: , какой из следующих методов лучше извлечь кэшированные изображения ?

  1. Используйте NSFetchRequest в cellForRowAtIndexPath: для извлечения кэшированного изображения (поэтомувыделение экземпляров NSFetchRequest во время прокрутки таблицы).

  2. Сохранить все кэшированные изображения с самого начала в источнике данных tableView, так что я могу просто извлечь их из (уже выделенного массива в viewDidLoad:) источник данных у меня UITableViewController.Этот метод явно занимает больше памяти, так как он выделяет кучу маленьких изображений, но я предполагаю, что прокрутка в итоге станет намного более плавной.

Может кто-нибудь подсказать мне об этом?

(Кстати, я хочу, чтобы изображения появлялись при прокрутке таблицы . Ожидание остановки прокрутки при загрузке изображений не вариант).


РЕДАКТИРОВАТЬ: загрузка изображений с диска

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

NSData *imageData = [NSData dataWithContentsOfFile:imageLocalPath];     
UIImage *userImage = [UIImage imageWithData:imageData];
cell.avatarImage = userImage;

Это все еще не гладко (есть небольшая задержка каждый раз, когда появляется новая ячейка (каждый раз, когда вызывается cellForRowAtIndexPath). Должен ли я сделать этот вызовАсинхронно? Или чтение с диска достаточно быстрое и определенно не является проблемой здесь?


РЕДАКТИРОВАТЬ: Подробнее

1. Где вы получаетеthe imageLocalPath?

URL-адрес изображения является частью моего dataSource, который представляет собой NSArray, выделенный в viewDidLoad (кэшируется в CoreData, но это не должно влиять на прокрутку). Путь к каталогу документов приложения также сохраняется вviewDidLoad, поэтому весь путь к файлу вычисляется в cellForRowAtIndexPath с использованием

NSArray *urlArray = [picURLString componentsSeparatedByString: @"/"];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsPath, [urlArray lastObject];

2. Что происходит, когда вы запускаете это через акулу?

Я никогда раньше не использовал Shark, пробовалиспользовать его и, по-видимому, iOS 4. больше не поддерживает его. Вы можете это подтвердить? Когда я нажимаю кнопку «Пуск», ничего не происходит.

3. Какой FPS вы получаете в Instruments на устройстве?

Я получаю от 25 до 30 кадров в секунду, но на самом деле это не выглядит так гладко на реальном экране.Не уверен, что это что-то значит.Я чувствую, что получаю 10-15 кадров в секунду.Опять же, плавная прокрутка между ячейками, просто когда табличное представление попадает в новую ячейку, возникает небольшая задержка (такая быстрая прокрутка = многие из этих маленьких задержек каждую секунду).

Ответы [ 3 ]

2 голосов
/ 11 августа 2010

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

Я бы включил альфа-тестирование в инструментах, прежде чем идти по этому пути.

Обновление

Интересно, мешает ли ваша загрузка данных сначала:

UIImage *userImage = [UIImage imageWithContentsOfFile:imageLocalPath];
[cell setAvatarImage:userImage];

То, что должно позволить UIImage сделать для вас некоторую кеширующую работу.

  • Где вы получаете imageLocalPath?
  • Хранится ли это в сущности базовых данных или идет расчет?
  • Что происходит, когда вы пропускаете это через акулу?
  • Какой FPS вы получаете в инструментах на устройстве?

Обновление 2

Почему вы берете объекты Core Data и сохраняете их в NSArray? Вы должны использовать NSFetchedResultsController в большинстве ситуаций.

Вы не должны создавать filePath, который занимает время, а -componentsSeparatedByString: выполняет поиск строки; очень медленно. Сохраните путь к файлу при сохранении изображения. Намного быстрее. Если вы не хотите менять свою модель, установите для нее временное значение, разрешенное в -awakeFromFetch:.

Функции Shark интегрированы с инструментами начиная с iOS4.

25-30 FPS не идеален, но довольно хорош. Это означает, что вы получаете хорошую частоту кадров, и незначительные изменения (в отношении основных фундаментальных проблем), вероятно, увеличат ее.

0 голосов
/ 10 августа 2010

Сохранение всех ваших изображений для справки не будет масштабируемым. Таким образом, убить старый iPod не займет много времени.

В моем опыте CoreData просто медленный. Не было бы хорошей идеей передавать объекты CoreData в табличное представление при прокрутке.

Это моя интерпретация того, что вы храните двоичные изображения в CoreData? Это может быть вашей проблемой. Возможно, вам нужно просто доверить дисковый ввод-вывод здесь. Я являюсь ведущим в приложении, у которого табличное представление с миниатюрами в два раза больше вашего, я делаю все свое кэширование вручную, записывая данные в файл на диске и извлекая их ... и если это не в кеше, я использую ASIHTTPRequest для тянуть.

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

0 голосов
/ 10 августа 2010

Я не очень знаком с использованием CoreData, но я думаю, что CoreData - это своего рода кеширование, поэтому, если вы кешируете его самостоятельно или используете NSFetchRequest, он окажется в памяти для быстрого доступа. Кроме того, мне не очень нравится CoreData, поскольку он сам по себе является базой данных, которая должна постоянно обновляться на сервере, что в конечном итоге оказывается неэффективным (ну, это мой собственный опыт) * ​​1001 *

Лично я бы пошел с чем-то по линии # 2. Так как вы можете использовать что-то вроде ASIHTTPRequest framework для выполнения всех ваших операций передачи, которые поддерживают кэширование и множество других параметров (например, очередь).

Кстати, проблема с изображениями, появляющимися после остановки прокрутки, связана просто с операциями прокрутки UIScrollView, происходящими вне основного цикла выполнения, это можно легко исправить, вызвав операции рисования в текущем цикле выполнения, и они будет отображаться при прокрутке (что, очевидно, повлияет на производительность, если вы будете делать тяжелые вещи в каждой ячейке)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...