Подтвердить что ты не робот

UITableView отскакивает назад в начало раздела при вызове reloadRowsAtIndexPaths

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

- (IBAction)handleCompleteTouchEvent:(UIButton *)sender {
    NSIndexPath *indexPath = [self.tableView indexPathForView:sender];
    id item = [self dataForIndexPath:indexPath];

    if ([item respondsToSelector:@selector(completed)]) {
        // toogle completed value
        BOOL completed = ![[item valueForKey:@"completed"] boolValue];
        [item setValue:[NSNumber numberWithBool:completed] forKey:@"completed"];

        [self.tableView beginUpdates];
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        [self.tableView endUpdates];
    }
}

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

4b9b3361

Ответ 1

Ах Ха! Я нашел проблему и собираюсь ответить на мой собственный вопрос для бедной души, которая столкнется с этим вопросом в будущем.

Все мои ячейки имеют переменную высоту, поэтому я использовал новый метод iOS7 в UITableViewDelegate, думая, что это может ускорить время рендеринга (не то, чтобы я действительно нуждался в нем):

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;

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

[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

Чтобы решить проблему отказов, я просто удалил переопределение этого метода оценочногоHeightForRowAtIndexPath, и теперь все работает так, как должно. Счастлив наконец.

Ответ 2

Вы должны иметь возможность делать то, что вы пытаетесь сделать, изменяя содержимое ячейки напрямую. Например, если вы используете базовый класс UITableViewCell, а данные в вашей модели - это NSString, которые вы показываете в ячейке таблицы, вы можете сделать следующее (после изменения модели данных) вместо вызова reloadRowsAtIndexPaths:

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *label = [cell textLabel];
label.text = @"New Value";

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

Ответ 3

Возможно, можно поместить ячейку в свой раздел и вызвать раздел перезагрузки:

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];

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

Ответ 4

В моем подобном случае мне пришлось настроить реализацию метода

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
...
}

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

Ответ 5

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

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

Динамические высоты также работали нормально, с этим исправлением проблем не возникало.

Ответ 6

Чтобы построить ответ xsee - я установил Estimate в конструкторе интерфейсов на "автоматический". Я изменил это на другой номер, и он начал работать. Я держал Row Height в автоматическом режиме.

Ответ 7

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

Ответ 8

Swift 4.2

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

 UIView.performWithoutAnimation({
                cell.configureSelection(isSelected: true)
                tableView.reloadSections([1], with: .none)
                tableView.allowsSelection =  false

            })