2013-04-04 5 views
2

У меня есть текстовое поле, которое показывает табличное представление предложений, когда пользователь вводит имя. Фильтрация источника данных производится в фоновом потоке, потому что это может занять некоторое время.Сбой при вызове reloadData UITableView слишком скоро после друг друга

- (IBAction)personNameChanged:(UITextField *)sender 
{ 
    NSString *name = sender.text; 

    [backgroundThread performBlock:^{ 
      [self.personsDataSource filterDataSourceByName:name]; 
      [mainThread performBlock:^{ 
       [self.autoCompleteTableView reloadData]; 
      }]; 
    }]; 
} 

[UITableView reloadData] звонки:

  • -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

... синхронно в то время как все клетки:

  • - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

... вызываются в более поздний момент времени.

Проблема заключается в том, что пользователь быстро набирает информацию о том, что filterDataSourceByName вызывается перед загрузкой всех ячеек. Затем вызывается cellForRowAtIndexPath для indexPath, который не существует.

Как решить эту проблему при вызове reloadData слишком быстро, чтобы не загружать все ячейки из последней перезагрузки?

ответ

8

распайка нового исходный массив данных для представления таблицы также должна быть сделана в основном потоке, что-то вроде:

- (IBAction)personNameChanged:(UITextField *)sender 
{ 
    NSString *name = sender.text; 
    [backgroundThread performBlock:^{ 
      // Store filtered array into separate array here: 
      NSArray *filteredPersons = [self.personsDataSource filterDataSourceByName:name]; 
      [mainThread performBlock:^{ 
       // Assign to table view data source array here: 
       self.dataSourceArray = filteredPersons; 
       [self.autoCompleteTableView reloadData]; 
      }]; 
    }]; 
} 

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

+1

Кажется работать, спасибо! Просто вопрос; это решение зависит от того, что все ячейки загружены, прежде чем мы снова войдем в блок mainThread. Мы уверены, что вся загрузка ячеек происходит до того, как мы снова войдем в mainThread performBlock? – thejaz

+0

@thejaz: Я не понимаю, почему это зависит от того, какие ячейки загружены или нет. –

+0

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

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