Элементы перемешались после прокрутки в UITableView - PullRequest
0 голосов
/ 13 апреля 2010

Когда я прокручиваю свой UITableView, ячейки смешиваются. Что я делаю не так?

Это мой метод:

- (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];
    }
    [cell insertSubview:[itemArray objectAtIndex:indexPath.row] atIndex:indexPath.row]; 
    return cell;
}

Обновление

Теперь он работает с помощью cell.contentView, но теперь, когда я выбираю элемент, выбранный элемент накладывается на содержимое другой ячейки ...

Ответы [ 2 ]

8 голосов
/ 13 апреля 2010

Советы TechZen здесь верны. Из вашего кода ясно, что вы неправильно поняли insertSubview: atIndex. Я подозреваю, что вам, вероятно, также нужно лучше понять, когда tableView: cellForRowAtIndexPath: делает и не вызывает.

К сожалению, здесь вы получили несколько плохих советов от sagar, которые могут еще больше сбить вас с толку, особенно потому, что вначале это может показаться работающим, но это снизит производительность прокрутки и использование памяти. Для его и вашей выгоды позвольте мне попытаться уточнить tableView: cellForRowAtIndexPath: и концепцию идентификатора повторного использования.

Ключом к пониманию tableView: cellForRowAtIndexPath: и идентификатора повторного использования является понимание того, что создание UITableViewCell является дорогостоящим. Рассмотрим все, что вам нужно сделать:

  1. Выделите ячейку
  2. Выделите подпредставления ячейки.
  3. Определить расположение подпредставлений в ячейке.
  4. Добавьте подпредставления в ячейку.
  5. Настройка свойств подпредставлений, таких как размеры шрифтов, цвета, перенос текста, изменение размеров и т. Д.
  6. Настройка свойств ячейки, таких как дополнительные изображения и т. Д.
  7. Определите определенный текст и / или изображения, которые должны отображаться в ячейке.

Когда мы создаем таблицу, мы обычно хотим, чтобы ячейки имели одинаковую базовую конфигурацию. Как правило, у них будет одинаковое количество подпредставлений, в одинаковых позициях, с использованием одинаковых шрифтов и т. Д. Фактически, единственное, что обычно должно меняться от одной ячейки к следующей, это пункт 7 в приведенном выше списке, текст и изображения, отображаемые ячейкой.

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

Apple признала необходимость оптимизации повторного использования ячеек, поэтому они встроили механизм для этого прямо в UITableView. Когда ячейка прокручивается за пределы экрана, UITableView не выбрасывает ее. Вместо этого он просматривает строку идентификатора повторного использования ячейки и помещает ячейку в специальный буфер, связанный с этим идентификатором. В следующий раз, когда вы вызовете dequeueReusableCellWithIdentifier: с тем же идентификатором UITableView извлечет ячейку из буфера и вернет ее вам для повторного использования. Эта ячейка все еще имеет те же подпредставления, в той же конфигурации, что и раньше, поэтому все, что вам нужно сделать, это шаг 7 в нашем списке. Просто обновите текст ячейки и / или изображения, и он готов к работе.

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

Сагар рекомендовал использовать разные идентификаторы повторного использования для каждой строки. Надеюсь, вы поймете, почему это плохая идея. Когда каждая ячейка прокручивается за пределы экрана, табличное представление будет смотреть на идентификатор ячейки, видеть, что оно уникально, и создавать новый буфер для этой конкретной строки. Если вы прокрутите 10000 строк, ваше табличное представление будет содержать 10000 буферов, каждый из которых будет выделен одной ячейке. Ваша прокрутка будет излишне медленной, пока вы создаете 10 000 объектов ячеек, и вашему приложению, вероятно, не хватит памяти, прежде чем вы доберетесь до нижней части таблицы.

Так что продолжайте и сохраните свой общий идентификатор ячейки. Внутри блока if (cell == nil) { } поместите весь установочный код, который будет общим для всех ячеек. Под этим блоком поместите только код, который заполняет содержимое, уникальное для каждой строки. Чтобы получить доступ к настраиваемым подпредставлениям, содержимое которых вы хотите изменить в каждой строке, вы можете использовать - [UIView viewWithTag:] или, что еще лучше, создать подкласс UITableViewCell и представить свои настраиваемые подпредставления как свойства вашего подкласса.

1 голос
/ 13 апреля 2010

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

Эта строка:

[cell insertSubview:[itemArray objectAtIndex:indexPath.row] atIndex:indexPath.row];

Берет представление из массива и добавляет его к подпредставлениям ячейки в определенном index.row существующего стека подпредставлений ячейки . Это не делает ничего, чтобы убедиться, что правильный вид вставлен в соответствующую ячейку. Если вы никогда не удаляете представления из предыдущей итерации, вы просто увидите, как все эти представления складываются в отдельные повторно используемые ячейки.

По крайней мере, вам нужно удалить все ранее добавленные подпредставления ячейки перед добавлением самого. Также следует добавлять подпредставления только в представление contentView ячейки, а не в саму ячейку.

Итак:

[[cell.contentView.subviews objectAtIndex:0] removeFromSuperview];
[cell.contentView addSubview:[itemArray objectAtIndex:indexPath.row]];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...