UITableViewCell селектор setSelected: animated: вызывается много раз? - PullRequest
15 голосов
/ 23 марта 2011

Я обнаружил странное поведение с setSelected: animated: в моем пользовательском классе UITableViewCell.Я обнаружил, что эта функция вызывается несколько раз, если я нажимаю на ячейку в моей таблице.Мне интересно, является ли это нормальным поведением или ошибкой в ​​моем коде.

Чтобы помочь с отладкой, я изменил функцию setSelected: animated: в моей собственной реализации класса UITableViewCell как таковой:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

[super setSelected:selected animated:animated];

// Configure the view for the selected state.
if (selected)
    NSLog(@"Yes %X", &self);
else
    NSLog(@"No %X", &self);

}

Если я нажму на ячейку в симуляторе, вот что я получу в консоли:

2011-03-22 22:05:26.963 marketPulse[3294:207] Yes BFFFDDD0
2011-03-22 22:05:26.964 marketPulse[3294:207] Yes BFFFDE30

Можно подумать, что я получу только 1 запись, так какЯ нажал только на 1 ячейку.

И если после этого я нажму на другую ячейку:

2011-03-22 22:07:11.014 marketPulse[3294:207] No BFFFD890
2011-03-22 22:07:11.016 marketPulse[3294:207] No BFFFDD00
2011-03-22 22:07:11.017 marketPulse[3294:207] Yes BFFFDDD0
2011-03-22 22:07:11.017 marketPulse[3294:207] Yes BFFFDE30

Если я нажму на одну и ту же ячейку 2 раза подряд, я получу больше, чем2 Да :

2011-03-22 22:08:41.067 marketPulse[3294:207] Yes BFFFDDD0
2011-03-22 22:08:41.068 marketPulse[3294:207] Yes BFFFDE30
2011-03-22 22:08:41.069 marketPulse[3294:207] Yes BFFFDE30

Чем больше раз я нажимаю на одну и ту же ячейку, тем больше Да я получу, и если после этого я нажму на другую ячейкуЯ получу много Нет

Я поставил точку останова перед NSLog, и, глядя на отладчик, кажется, что все повторяющиеся вызовы исходят из одного и того же объекта.

Вот часть моей функции tableView: cellForRowAtIndexPath: , так что вы можете увидеть, как мойобрабатываются ячейки:

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


static NSString *ContentCellIdentifier = @"newsTableCellContent";

UITableViewCell *cell;


//index of cell data in tableData
NSUInteger index = indexPath.row / 2;

...

//content of story
else if( [indexPath row] % 2 == 1 ) {

    cell = [tableView dequeueReusableCellWithIdentifier:ContentCellIdentifier];

    if (cell == nil) {
        NSArray *topLevelObjects = [[NSBundle mainBundle]
                                    loadNibNamed:@"newsTableCells"
                                    owner:nil options:nil];

        for (id currentObject in topLevelObjects) {
            if ( [currentObject isKindOfClass:[newsTableCellContent class]] ) {
                cell = currentObject;
                break;
            }
        }
    }

    ((newsTableCellContent *)cell).content.text = [[tableData objectAtIndex:index] description];

}   

return cell;
}

Все работает нормально, поэтому сложно определить, являются ли повторные вызовы setSelected: animated: преднамеренными или нет.Если это нормальная операция, я могу обойтись другим методом, но я просто хотел бы знать, должно ли это произойти или нет.

Спасибо

Ответы [ 4 ]

14 голосов
/ 03 октября 2012

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

Поскольку при повторном просмотре большого табличного представления ячейки используются повторно, табличное представление должно сохранять список выбранных ячеек отдельным.Не только это, но всякий раз, когда он повторно использует ячейку, он должен установить свое выбранное свойство, потому что он может использовать старое недопустимое состояние selected из предыдущего воплощения.случается: ранее выбранная ячейка отменяется (используя setSelected:).Новая ячейка подсвечивается.Он будет выделен (по крайней мере, если вы нажмете, вместо того, чтобы удерживать палец), и метод setSelected: вызывается, потому что была выбрана новая ячейка.Это один.

Второй вызов - это отложенный вызов выполнения, возможно, из точки, где представление таблицы еще не знает, каким будет конечное состояние таблицы.Этот вызов переходит к _selectAllSelectedRows, который, как следует из названия, вызывает setSelected: animated: во всех выбранных строках.Это второй звонок.Причиной этого, скорее всего, является решение потенциальных проблем из-за того, что табличное представление находится в состоянии «перехода», но кто знает.

Является ли это ошибкой или нет, она подлежит интерпретации.Исправление для дублирующих вызовов заключается в следующем:

if (self.selected == selected) return;

прямо перед вызовом super (вам не нужно звонить super, если self.selected == selected).

3 голосов
/ 07 января 2017

В идеале вы не должны вызывать setSelected из любого места в вашем коде. UIKit позаботится об этом.

Если вы хотите отобразить ячейку / строку, выбранные в cellForRowAtIndexPath , просто вызовите

tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .None)

для этого конкретного indexPath.

Опять никогда не вызывайте setSelected явно, если вы действительно не хотите.

2 голосов
/ 05 августа 2015

Это нормальное поведение, если вы используете iPad.(он вызывается только один раз на iPhone).

Чтобы прекратить получать множественное «setSelected: YES» или множественное «setSelected: NO», все, что вам нужно сделать, это:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

Теперь, один щелчок по любой ячейке дает вам:

  • 1 запись набора Выбрано: ДА анимировано: НЕТ
  • 1 запись tableView: didSelectRowAtIndexPath:
  • 1запись setSelected: NO animated: YES

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

1 голос
/ 18 октября 2011

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

Если вы действительно хотите увидеть, что происходит, добавьте NSLog в tableView: cellForRowAtIndexPath: который будет регистрировать indexPath и возвращенную ячейку.

Весь журнал должен дать вам хорошее понимание того, что происходит внутри и почему. Я предполагаю, что это будет что-то вроде этого (нажал на IndexPath 1: 1)

Дайте мне ячейку на 1: 0 (ранее выбранная ячейка).
Отмените выбор 1: 0
Дайте мне ячейку снова 1: 0 (обновлено после отмены выбора)
Отмените выбор 1: 0 (обновите выбранный флаг в этой ячейке и запустите анимацию)
Дайте мне клетку на 1: 1
Выберите 1: 1
Дайте мне ячейку снова 1: 1 (обновляется после выбора)
Выберите 1: 1 (обновить выбранный флаг в этой ячейке и запустить анимацию)

Повторный щелчок по выбранной ячейке лишь немного отличается - вместо отмены выбора он вызывает другое обновление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...