UITableViewCell повторное использование: неправильно отображается ячейка - не используется повторно, как ожидалось
Я создал список с несколькими вариантами, который позволяет выбирать несколько ингредиентов.
в моем tableview ячейки могут быть включены или отключены на основе свойства list ингредиента. Если задано свойство списка ингредиентов, ячейка будет отключена.
однако, когда ячейка повторно используется, она не отображается, как я ожидал. Изображения ниже объясняют проблему более эффективно, чем я могу.
(ингредиенты, которые должны не включаются: глазурь для торта, сгущенное молоко и Курфлюр.)
на первом изображении показаны три ингредиента, отключенные и аннотированные, как ожидалось.
однако во втором изображении прокрутка вниз показывает, что некоторые ингредиенты отключены (но вы можете выбрать их, и они имеют полное взаимодействие).
третье изображение показывает список после прокрутки назад наверх. Некоторые ингредиенты были выделены серым цветом, и обратите внимание, как кукурузная мука отображается как включено, даже если вы не можете взаимодействовать/выбрать его.
проблема заключается в повторном использовании ячеек. Похоже, что ячейка не получает " сброс "при повторном использовании, и поэтому сохраняет часть своего" старого " внешнего вида.
ниже есть код 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. Это не имеет ничего общего с вашей проблемой, но это самый последний способ сделать это для представления таблицы в раскадровка.