Я думаю, прочитав о том, что вы пытаетесь сделать, вы немного ошибаетесь.Вы не должны делать асинхронную работу в cellForRowAtIndexPath
, потому что не можете быть уверены, что ячейка, которую вы обновляете позже, является правильной.
Рассмотрите ваш код:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
...
return cell;
}
Итак, вы создаете ячейку и возвращаете ее.Это может быть один из очереди повторного использования или новый.Все идет нормально.Но затем вы добавляете этот код:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSInteger row = [indexPath row];
cell.textLabel.text = [[NSString alloc] initWithFormat:@"%d", row];
dispatch_async(dispatch_get_main_queue(), ^{
[cell setNeedsLayout];
});
});
Итак, вы отправляетесь в фоновую очередь, чтобы установить что-то в этой ячейке.Но что произойдет, если произойдет такой ход событий:
Таблица запрашивает ячейку.
Новая ячейка создана, ячейка A, отправка получаетсделано, чтобы установить вещи позже.
Пользовательские прокрутки и ячейка A выводятся из вида и помещаются в очередь повторного использования.
Таблица запрашиваетячейка.
Ячейка A возвращается из пула повторного использования, и очередная отправка помещается в очередь.
Первая отправка заканчивается, установка параметров в ячейку A.
Это не то, что вам нужно, так как теперь ячейка A содержит старые данные.Конечно, если ваша очередь последовательная, вам, возможно, удастся с ней справиться, поскольку 2-я отправка всегда завершится после первой, но а) это нехорошо, поскольку устаревшие данные все равно будут видны, и б) ваша очередь может быть параллельной очередью.в любом случае.
Итак, какое правильное решение вы спросите?Ну, мой обычный подход к этому - иметь собственную ячейку.Похоже, вы хотите, чтобы ячейка загружала изображение, и я предполагаю, что вы хотите загрузить это изображение из Интернета?Таким образом, мой способ сделать это состоит в том, чтобы иметь пользовательскую ячейку с методом loadImage
, который вызывается в каждой видимой ячейке, когда табличное представление либо перестало прокручиваться и не замедляется, либо табличное представление перестало замедляться.(См. UIScrollViewDelegate
методы для того, что я имею в виду).
Затем в методе loadImage
я запускаю HTTP-запрос, чтобы получить изображение, и жду его возвращения и устанавливаю UIImageView
в моемПользовательская ячейка для изображения возвращается.Важным дополнительным битом является то, что у меня есть установщик в пользовательской ячейке для установки объекта / URL / того, что ячейка отображает, которая дает информацию о том, какое изображение загружать.Затем, когда ячейка получает запрос на новый URL, она отменяет старый и запускает новый при следующем вызове loadImage
.
Надеюсь, это имеет смысл!Я на самом деле делаю это немного по-другому, но это настолько простое описание, которое я могу дать для общей идеи.К сожалению, у меня нет кода для показа, но, пожалуйста, задавайте любые вопросы, и я постараюсь добавить его еще.