2012-06-30 4 views
9

У меня есть UITableView, который заполнен неизвестным количеством строк. Каждая строка содержит (например, 3) изображения, и приложение собирает эту информацию из веб-службы.UITableView с бесконечной прокруткой и ленивой загрузкой

Для UITableView Я реализовал бесконечную прокрутку. Всякий раз, когда таблица почти достигает конца текущего количества строк, я инициирую вызов в веб-службу, чтобы получить следующие 50 строк данных. Я делаю это в методе scrollViewDidScroll, который вызывается UITableView.

- (void) scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    CGFloat actualPosition = scrollView.contentOffset.y; 

    float bottomOffset = 450; 
    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) 
     bottomOffset = 1000; 

    CGFloat contentHeight = scrollView.contentSize.height - bottomOffset; 
    if (actualPosition >= contentHeight && !_loading && !_cantLoadMore) 
    { 
     self.loading = YES; 

     _currentPage++; 

     NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; 
     [dict setObject:[NSNumber numberWithInt:_currentPage] forKey:@"page"]; 
     [dict setObject:[_category objectForKey:@"ID"] forKey:@"category"]; 

     [self performSelectorInBackground:@selector(getWallpapersInBackground:) withObject:dict]; 
    } 
} 

Изображения в строках UITableView ленивы загружены. Всякий раз, когда строка видима, изображения загружаются в отдельный поток, и строки обновляются после полной загрузки изображения. Принцип, который я использую для ленивой загрузки, аналогичен тому, как Apple предлагает в своей документации. Изображение также добавляется к локальному NSDictionary, поэтому я могу получить его, когда строка прокручивается из экрана и обратно (и строка воссоздана).

Поскольку количество изображений в одном представлении может увеличиться до 2000 - 3000, я также кэширую изображения на диск и очищаю изображения от NSDictionary, когда они находятся дальше, чем X строк. Когда пользователь прокручивает вниз и снова происходит следующее:

  1. Новые строки отображаются
  2. Ленивый метод загрузки называется, которая проверяет, если изображение присутствует на диске, или что он должен загрузить его.
  3. Когда изображение загружается или извлекается с диска, он выполняет кодовый блок, который отображает изображение в строке. Изображения, загруженные из Интернета, также кэшируются на диск.
  4. UIImage добавлен в NSDictionary для более быстрого кэширования изображений, которые должны быть в пределах досягаемости.
  5. Изображения, которые находятся в строках, 15 строк или дальше от видимых строк, удаляются из NSDictionary из-за проблем с памятью (слишком много UIImage объектов в NSDictionary вызывают ошибки из-за памяти).

Когда UITableView почти доходит до конца, происходит следующее:

  1. UITableView почти достигает конца загруженных строк
  2. вызовов в WebService, с нагрузками новых рядов (50)
  3. Новые строки добавляются в массив, который используется для метода numberOfItemsInSection.
  4. A reloadData вызывается, чтобы убедиться, что UITableView заполняется дополнительными новыми строками.
  5. Новые строки, содержащие изображения, выполняют описанные выше шаги для ленивой загрузки изображений.

Итак, проблема заключается в том, что я добавляю новые записи из веб-службы. Когда я вызываю reloadData на UITableView, некоторые изображения снова загружаются с диска, и при прокрутке появляются некоторые завитки.

Я ищу решение для этого.Я попытался использовать insertItemsAtIndexPaths с количеством новых строк, чтобы добавить их в UITableView, но это делает мой ленивый метод загрузки уже загружает изображения (потому что так или иначе все ячейки создаются в то время, даже когда они не видны, проверяя, ячейка видна во время создания, дает неожиданные результаты, изображения не загружаются, ячейки выглядят странно и т. д.).

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

+0

[KTPhotoBrowser] (https://github.com/kirbyt/KTPhotoBrowser) - очень хорошая библиотека для просмотра, загрузки и кеширования фотографий. Вы можете изменить его в соответствии с вашими потребностями. – Hejazi

ответ

13

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

  • Я использовал -tableView:cellForRowAtIndexPath: как свой реплик для загрузки большего количества данных из Интернета. Я выбрал номер (в моем случае 10), когда indexPath.row + 10 >= self.data.count загрузите больше данных.

    • Мне нужно было позвонить -tableView:cellForRowAtIndexPath: в любом случае.
    • Я не заставлял обратный вызов в более плотную петлю -scrollViewDidScroll:.
  • Я подклассы UIImageView с классом, который ASync образы загрузки, которые я призывал URLImageView.

    • В -tableView:cellForRowAtIndexPath: я присвоил URL-адрес экземпляру URLImageView.
    • Это назначение вызвало фоновую операцию, которая либо загружалась с диска, либо загружалась из Интернета.
    • Операция была отменена, поэтому я не работал над изображением, которое больше не нуждалось в загрузке.

Я имел вид таблицы с сотнями (но не тысячами) изображений. У меня было только 2 или 3 ячейки таблицы на экране одновременно.

  • Я использовал -refreshData: он работал как чемпион.
  • У меня даже есть URLImageView, чтобы исчезнуть на изображении. Это был очень хороший эффект.

Я надеюсь, что это поможет.

+0

Можете ли вы PLZ разработать немного .. Я сталкиваюсь с той же проблемой. – Rakesh

+0

Я не уверен, что вы хотите разработать? В '-tableView: cellForRowAtIndexPath:', 'if (indexPath.row + 10> = self.data.count) {[self.data loadNextChunkWithCompletion:^{[tableView reloadData]; }]; } ', где' self.data' - это модель данных с частично загруженными данными и '-loadNextChunkWithCompletion:' - метод, который загружает следующую часть данных. –

2

, чтобы избежать мерцающей попытки позвонить beginUpdates на стол, затем insertrowAtIndexPaths:withRowAnimations: и закончите с endUpdates.

Удачи.

Смежные вопросы