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

IOS UItableview scrollToRowAtIndexPath больше не работает

Сегодня утром я только что установил новый Xcode, который включает iOS 6.

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

Пользователь выбирает главу и строку, и представление таблицы автоматически прокручивается в нужное положение (в viewDidLoad).

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];
[self.tableView scrollToRowAtIndexPath:indexPath 
    atScrollPosition:UITableViewScrollPositionTop animated:YES];

это отлично работает в симуляторе iOS5.

Пробовав это в симуляторе iOS 6, прокрутка не выполняется. У меня нет ошибок. Я проверил, linePos и ​​chapterPos получают правильные значения, но прокрутка не выполняется.

Любые идеи, почему?

4b9b3361

Ответ 1

Для последних версий iOS, пожалуйста, прочитайте ответ Fyodor Volchyok. Обратите внимание, что это не отмечено как принятый ответ просто потому, что в то время, когда вопрос был впервые задан (сентябрь 2012 г.), текущий ответ было рабочим решением. Более свежие версии iOS также получили ту же проблему, которая теперь решена в ответ Федором Волчиком, поэтому в этот момент вы должны ответить +1.


Я нашел ответ. Я должен сначала перезагрузить данные в tableview

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:linePos inSection:chapterPos];

[self.tableView reloadData];

[self.tableView scrollToRowAtIndexPath:indexPath 
    atScrollPosition:UITableViewScrollPositionTop animated:YES];

Даже если я нашел ответ, я не знаю, почему он работает в iOS5, а не в iOS6.

ИЗМЕНИТЬ

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

UItableview scrollToRowAtIndexPath не отображает последнюю строку правильно

Поскольку @Raj также попросил об этом, я должен сказать, что я запускал это в viewDidLoad. Чтобы исправить проблему последней строки, не отображаемой правильно, мне пришлось поместить ее в viewDidAppear.

Ответ 2

Objective-C

[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
        NSIndexPath *rowIndexPath = [NSIndexPath indexPathForRow:3 inSection:0];
        [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
});

Swift

tableView.reloadData()
DispatchQueue.main.async {
    let indexPath = IndexPath(row: linePos, section: chapterPos)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}

Ответ 3

Я добавляю этот ответ в качестве дополнения к Fyodor Volchyok. Я также обнаружил, что диспетчер решает проблему. Я смог найти обходное решение, которое не отправляет.

self.tableView.reloadData()
let index = // the desired index path

// For some reason, requesting the cell prior to 
// scrolling was enough to workaround the issue.
self.tableView.cellForRowAtIndexPath(index)

self.tableView.scrollToRowAtIndexPath(index, atScrollPosition: .Top, animated: false)

Ответ 4

Я столкнулся с другой проблемой (вероятно, с ошибкой) с scrollToRowAtIndexPath специально для iPhone X с ios11. Моя таблица имеет несколько сотен секций, а в режиме с обрушением ~ 10 будет помещаться на видимом экране. По мере того, как indexPath становился все глубже, прокрутка постепенно отставала.

Например, когда я хотел, чтобы поиск нашел элемент в строке 30, ScrollPositionTop имел бы одну дополнительную строку до того, как фактическая строка я ожидаю быть наверху.

И когда я тестировал поиск более глубоких строк, он начал падать еще больше, где, скажем, что-либо за 100 строк в глубину или около того, ожидаемая строка даже не попадала в видимую область.

Обходной путь, который я нашел до сих пор, это сказать анимированный: НЕТ для прокрутки в dispatch_async, тогда он работает без каких-либо сбоев.

Ответ 5

После iOS7 свойство automaticallyAdjustsScrollViewInsets UIViewController по умолчанию - YES. Это приведет к тому, что система будет настраивать contentOffset tableView при нажатии контроллера представления. Даже вы вызываете [self.tableView scrollToRowAtIndexPath:rowIndexPath atScrollPosition:UITableViewScrollPositionNone animated:NO]; в viewWillAppear. contentOffset также будет изменен системой после viewWillAppear. Итак, мое решение:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = NO;

    /// any other codes
}

- (void)viewWillLayoutSubviews {
    self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    // change tableView data source

    [self.tableView reloadData];
     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.dataSourceArray count] - 1 inSection:0];
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
}

Ответ 6

Фёдор Волчик отвечает в Свифте:

tableView.reloadData()
let indexPath = NSIndexPath(forRow: linePos, inSection: chapterPos)
// make sure the scroll is done after data reload was finished
dispatch_async(dispatch_get_main_queue()) {
   self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

Ответ 7

Это сработало для меня в ios11

self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionFooterHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0

dispatch_async(dispatch_get_main_queue(), ^{
   NSInteger numberOfSections = self.tableView.numberOfSections;
   if (numberOfSections > 0)
   {
     NSInteger lastSection = numberOfSections - 1;
     NSInteger lastRowInLastSections = [self.tableView numberOfRowsInSection:lastSection] - 1;

     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastRowInLastSections inSection:lastSection];
     [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:isAnimated];
}
});

Ответ 8

Еще один возможный обходной путь - вызвать layoutIfNeeded перед вызовом scrollToRowAtIndexPath.

[self.view layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath...];