24

今天早上我刚刚安装了包含 iOS 6 的新 Xcode。

我有一个表视图,其中加载了一个包含章节和行的 plist 文件。章节定义了部分。

用户选择章节和行,表格视图会自动滚动到正确的位置(在 viewDidLoad 中)。

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

这在 iOS5 模拟器中效果很好。

在 iOS 6 模拟器中尝试此操作不会执行滚动。我没有错误。我检查过, linePos 和 chapterPos 收到正确的值,但没有执行滚动。

任何想法为什么?

4

9 回答 9

68

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];
});

迅速

tableView.reloadData()
DispatchQueue.main.async {
    let indexPath = IndexPath(row: linePos, section: chapterPos)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
于 2014-12-12T15:40:13.390 回答
29

对于最新版本的 iOS,请阅读 Fyodor Volchyok 的回答。请注意,它没有被标记为已接受的答案,仅仅是因为在首次提出问题时(2012 年 9 月),当前答案是有效的解决方案。更新版本的 iOS 也遇到了同样的问题,现在 Fyodor Volchyok 的回答已经解决了这个问题,所以你应该在那一刻 +1 他的回答。


我找到了答案。我必须先重新加载表格视图中的数据

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.

于 2012-09-21T08:11:55.827 回答
3

这适用于 iOS 12 和 13:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { 
    self.tableView.scrollToRow(at: IndexPath(row: 0, section: 1), at: .bottom, animated: true) 
}
于 2020-01-17T15:47:17.833 回答
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)
于 2016-01-05T17:00:09.417 回答
2

我在运行 ios11 的 iPhone X 上遇到了另一个与 scrollToRowAtIndexPath 相关的问题(可能是一个错误)。我的桌子有几百个部分,在折叠模式下,~10 可以放在可见屏幕中。随着 indexPath 越来越深,滚动逐渐落后。

例如,当我希望搜索找到第 30 行中的项目时,ScrollPositionTop 将在我希望位于顶部的实际行之前多出一行。

当我测试搜索更深的行时,它开始落后于甚至超过 100 行深左右的任何东西,预期的行甚至没有出现在可见区域中。

到目前为止,我发现的解决方法是对 dispatch_async 中的滚动说动画:NO,然后它可以正常工作而不会出现任何故障。

于 2017-11-28T22:18:12.943 回答
1

iOS7 之后automaticallyAdjustsScrollViewInsetsUIViewController 默认的属性是YES. 当视图控制器被推送时,它会导致系统调整contentOffsettableView 的值。即使你打电话[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];
}
于 2015-12-17T08:27:32.453 回答
1

另一种可能的解决方法是在调用layoutIfNeeded之前先调用scrollToRowAtIndexPath

[self.view layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath...];
于 2019-07-10T11:55:01.210 回答
0

Fyodor Volchyok 在 Swift 中的回答:

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)
}
于 2016-10-23T07:54:32.840 回答
0

它在 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];
}
});
于 2017-10-12T06:20:15.447 回答