UITableViewCell повторное использование: неправильно отображается ячейка - не используется повторно, как ожидалось

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

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

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

(ингредиенты, которые должны не включаются: глазурь для торта, сгущенное молоко и Курфлюр.)

  1. на первом изображении показаны три ингредиента, отключенные и аннотированные, как ожидалось.

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

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

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

ниже есть код cellForRowAtIndexPath:, поскольку я уверен, что проблема именно в этом (хотя я не вижу, что не так).

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }    

    // Fetches the corresponding Ingredient from the ingredientArray
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already in your Lardr";
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already on your Shopping List";
    }
    else
    {
        cell.userInteractionEnabled = YES;
        cell.detailTextLabel.text = @"";
    }

    // Add a checkmark accessory to the cell if the ingredient is on the selectedIngredients array
    if ([self.selectedIngredients containsObject:ingredient])
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        cell.accessoryType = UITableViewCellAccessoryNone;

    cell.textLabel.text = ingredient.name;

    return cell;
}

Я в тупике пытаюсь разобраться в этом, и я прочитал все так вопросы, которые даже отдаленно связаны, но безрезультатно. В чем проблема?!


моя логика заключается в том, что для каждой ячейки устанавливаются свойства textLabel, detailTextLabel, userInteractionEnabled и accessoryType, независимо от того, какой путь выполнения через операторы if, поэтому я не вижу, почему даже после повторного использования ячейка отображается неправильно.


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

cell.userInteractionEnabled = YES;
cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
cell.accessoryType = UITableViewAccessoryNone;

однако, что интересно и совершенно нелогично-когда я переместил следующую строку cell.textLabel.text = ingredient.name прямо под строку Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];, абсолютно никакой стиль не применяется к любой ячейке, даже если userInteraction установлен ниже (и соответствующие ячейки отключены как ожидаемый.)

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


Update: я решил проблему; см. Мой ответ ниже.

4 ответов


установите цвет вашей ячейки явно в willDisplayCell

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

 Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else
    {
        cell.textLabel.textColor = [UIColor blackColor];
    }

}

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

я исправил проблему, установив текст ячейки перед настройкой свойства userInteractionEnabled. Однако к ячейке не применялся стиль (хотя ячейка была отключена). Поэтому мне пришлось вручную стилизовать ячейку, установив textColor ячейки. Ниже приведен скорректированный код с комментариями.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    } 

    // Fetches the relevent ingredient from the ingredientArray
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];
    cell.textLabel.text = ingredient.name; // Moved this line before setting userInteractionEnabled

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already in your Lardr";
        cell.textLabel.textColor = [UIColor grayColor]; // Update the color accordingly
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already on your Shopping List";
        cell.textLabel.textColor = [UIColor grayColor];
    }
    else
    {
        cell.userInteractionEnabled = YES;
        cell.detailTextLabel.text = @"";
        cell.textLabel.textColor = [UIColor blackColor];
    }

    // Add a checkmark accessory to the cell if the ingredient is on the selectedIngredients array
    if ([self.selectedIngredients containsObject:ingredient])
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        cell.accessoryType = UITableViewCellAccessoryNone;

    return cell;
}

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


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

декларация

 TableViewCell *_selectedCell; 

настройка строки для хранения выбранной ячейки и поддержания списка выбора .

_selectedCell = (TableViewCell*)[self.ItemTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowIndex inSection:0]];

в cellforrowatindexpath проверьте текущую ячейку в

if(_selectedCell)
        [cell setBackgroundColor:[UIColor whiteColor]];// Customize the cell 

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

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Fetches the corresponding Ingredient from the ingredientArray
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already in your Lardr";
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already on your Shopping List";
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else
    {
        cell.userInteractionEnabled = YES;
        cell.detailTextLabel.text = @"";
        cell.textLabel.textColor = [UIColor blackColor];
    }

    if ([self.selectedIngredients containsObject:ingredient])
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        cell.accessoryType = UITableViewCellAccessoryNone;

    cell.textLabel.text = ingredient.name;

    return cell;
}

обратите внимание, что я использую dequeueReusableCellWithIdentifier: forIndexPath: вместо dequeueReusableCellWithIdentifier: и исключаю предложение if. Это не имеет ничего общего с вашей проблемой, но это самый последний способ сделать это для представления таблицы в раскадровка.