Сохранение позиции прокрутки после перезагрузки в tableView

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

Проблема в том, что пользователь может прокручивать вверх/вниз tableView. Мне нужно прокрутить tableView, чтобы ячейка была точно такой же UITableViewScrollPosition, как и до обновления.

Очевидно, я сохраняю последний нажатый элемент

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    _lastSelectedItem = [self itemForIndexPath:indexPath];
} 

Затем после перезагрузки tableView:

NSIndexPath *indexPath = [self indexPathForItem:_lastSelectedItem];
if (_tableView.numberOfSections > indexPath.section && [_tableView numberOfRowsInSection:indexPath.section] > indexPath.row) {
    [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
    _lastSelectedItem = nil;
}

Было бы хорошо, но... пользователь не смог закончить на UITableViewScrollPositionMiddle. Он мог закончить прокрутку на UITableViewScrollPositionTop или UITableViewScrollPositionBottom или даже где-то посередине.

-- редактировать --

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


person Nat    schedule 24.09.2014    source источник


Ответы (1)


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

- (void)refresh {
    [self saveLastScrollPosition];
    [self reloadData]; // inside we reload data + reload tableView
    [self scrollToLastScrollPosition];
}

- (NSInteger)heightToMinYOfCellAtIndexPath:(NSIndexPath *)indexPath {
    NSInteger sections = indexPath.section;
    NSInteger totalRows = 0;
    for (NSInteger section = 0; section < indexPath.section; section++) {
        totalRows += [self.tableView numberOfRowsInSection:section];
    }
    totalRows += indexPath.row;

    return ((sections + 1) * kHeaderHeight + totalRows * kRowHeight);
}

- (void)saveLastScrollPosition {
    if (_lastSelectedItem) { // make sure we have that item selected
        NSIndexPath *indexPath = [self itemForItem:_lastSelectedItem];
        NSInteger aboveItemHeight = [self heightToMinYOfCellAtIndexPath:indexPath];
        CGFloat contentOffsetY = self.tableView.contentOffset.y;
        _previousOffset = aboveItemHeight - contentOffsetY;
    }
}

- (void)scrollToLastScrollPostion {
    if (_lastSelectedItem) { // make sure we have that item selected
        NSIndexPath *indexPath = [self itemForItem:_lastSelectedItem];
        if (self.tableView.numberOfSections > indexPath.section && [self.tableView numberOfRowsInSection:indexPath.section] > indexPath.row) { // make sure the indexPath still exist after reload
            NSInteger aboveItemHeight = [self heightToMinYOfCellAtIndexPath:indexPath]; // height of items above selected index
            CGPoint offset = CGPointMake(0.f, aboveItemHeight - _previousOffset);
            // in case index should be higher: eg earlier item was at index (4,8) now is at (0,0)
            if (offset.y < 0) {
                offset.y = 0;
            }
            [self.tableView setContentOffset:offset animated:NO]; // just jump, user shouldn't see this
            _previousOffset = 0; // forget the calculated values
            _lastSelectedItem = nil;
        }
    }
}
person Nat    schedule 24.09.2014
comment
Его можно поместить в категорию UITableView с помощью одного общедоступного метода reloadDataAndScrollToLastPosition. - person ingaham; 07.01.2015
comment
если предположить, что высота ячейки uitableview динамическая, а также заголовок также является динамическим, и мы будем использовать несколько пользовательских ячеек, так что мы можем сделать, пожалуйста, объясните это............. - person Jatiendar Kumar; 25.10.2015
comment
@JatiendarKumar Объясните Зависит от того, как вы это реализовали. Вы можете посмотреть на raywenderlich.com/73602/ примерно в середине страницы вы можете увидеть такой метод heightForBasicCellAtIndexPath: и взять его за пример. - person Nat; 26.10.2015
comment
Это дубликат сообщения: stackoverflow.com/a/18844780/3705567 - РАБОТАЕТ! (Я) - person A. Trejo; 24.05.2016