2014-11-11 4 views
-1

У меня есть мой метод cellForRowAtIndexPath делегата определяется так:UITableView вызова метода делегата, когда DataSource пуст

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    PLOTCheckinTableViewCell *cell = (PLOTCheckinTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CheckinCellIdentifier forIndexPath:indexPath]; 
    if([self.items count] == 0){ 
     return cell; 
    } 
    NSDictionary *checkin = self.items[indexPath.row]; 
    // configure and return custom cell 
} 

Я использую пользовательский класс клеток (PLOTCheckinTableViewCell).

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

Поместив это IF, проверьте выше, я смягчил крах.

Однако

  1. Почему именно не делаю мою IF проверки «работа», я вижу никаких видимых последствий возвращения клетки, прежде чем он был настроен. Это запутывает

  2. Есть ли какие-либо лучшие способы защиты от этого события (т. Е. Данные таблицы перезагружаются пустым массивом)? Конечно, numberOfRowsInSection вернул бы array count, который был бы 0? (Если он был пустой массив)

EDIT (далее код)

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    float count = [self.items count]; 
    return count; 
} 

- (void)resetData { 
    self.items = [NSMutableArray array]; 
} 

-(void) refreshInvoked:(id)sender forState:(UIControlState)state { 
    [self resetData]; 
    [self downloadHomeTimeline]; 
    [self.refreshControl endRefreshing]; 
} 

- (void)downloadHomeTimeline { 
    [self.apiClient homeTimeline:self.page completionBlock:^(NSDictionary *data){ 
     for (NSDictionary *obj in data[@"items"]) { 
      [self.items addObject:obj]; 
     } 
     [self.itemsTableView reloadData]; 
    }]; 
} 
+0

Может быть, это поможет увидеть реализацию для pull для refresh и numberOfRowForSection, если есть что-то вроде второго pull, изменяет содержимое массива items после того, как numberOfRowForSection вернул ненулевое число. Недавно я заметил, что есть заметная задержка после того, как numberOfRowForSection вернулся и вызывается cellForRowAtIndexPath. – Antenehs

+0

@Antenehs yep, это звучит правильно. Отредактированный вопрос для ясности – benhowdle89

+0

Вы должны вернуть счетчик 'items' в' numberOfRowsInSection: 'и' reloadData' в представлении таблицы, как только 'items' будет заполнен допустимыми данными. –

ответ

2

Я несколько вещей, которые я хотел бы предложить, чтобы сделать. Убедитесь, что [self.itemsTableView reloadData] выполнен на основном потоке, а также я бы поставил [self.refresControl endRefreshing] в блок завершения. Таким образом, он остановит обновление после его завершения, и вы не должны позволять пользователю более одного раза одновременно.

- (void)downloadHomeTimeline { 
     [self.apiClient homeTimeline:self.page completionBlock:^(NSDictionary *data){ 
      for (NSDictionary *obj in data[@"items"]) { 
       [self.items addObject:obj]; 
      } 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [self.itemsTableView reloadData]; 
       [self.refreshControl endRefreshing]; 
      }); 

     }]; 
    } 

Также в numberOfRowsInSection просто возвращает кол

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return [self.items count]; 
} 

Чтобы добавить к ответу. Вы не должны сбросить массив до получения новых данных. При получении новых данных пользователь все еще может прокручивать таблицу, и это означает, что будут созданы новые ячейки, но ваш NSMutableArray не будет иметь никаких данных. То есть, когда вы получаете ошибку и приложение падает. Вам нужно было бы [tableView reloadData], чтобы очистить таблицу, чтобы tableView знал, что есть 0 строк, и я не думаю, что это ваше намерение.

Сообщите мне, если это решает проблему.

+0

Благодарю вас, и Бог благословит вас. Это был хороший совет, чтобы перезагрузить таблицу из основного потока.Я много понесся по пути загрузки таблицы медленно (> 10 секунд) при перезагрузке из блока завершения. CellForRow просто не вызывался в течение долгого времени после того, как numberOfRowsForSection вернулась. Тогда я просто решил, что это ошибка, и представил мое медленное приложение, как есть. Время для обновления сейчас. Я сказал спасибо? – Antenehs

+0

Это здорово !!! :) Все, что связано с пользовательским интерфейсом, должно выполняться в основном потоке. В противном случае он может работать неправильно. Счастливое кодирование! – Yan

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