ChatGPT解决这个技术问题 Extra ChatGPT

UITableView - 滚动到顶部

在我的表格视图中,我必须滚动到顶部。但我不能保证第一个对象将是第 0 行第 0 行。可能是我的表格视图将从第 5 部分开始。

所以我得到一个例外,当我打电话时:

[mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

还有另一种方法可以滚动到表格视图的顶部吗?


c
catlan

UITableView 是 UIScrollView 的子类,所以你也可以使用:

[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

或者

[mainTableView setContentOffset:CGPointZero animated:YES];

在 Swift 中:

mainTableView.setContentOffset(CGPointZero, animated:true)

在 Swift 3 及更高版本中:

mainTableView.setContentOffset(.zero, animated: true)

我首先用 CGRectZero 尝试了这个,它相当于 CGRectMake(0, 0, 0, 0)。这不起作用,但奇怪的是上面的方法。我想它需要一个正的宽度和高度。谢谢你。
请注意,如果您在 scrollToRowAtIndexPath: 中运行它,您将需要动画:NO 以使表格从正确的位置开始。希望能帮助到你!
@hasan83 CGRectMake(0, 0, 0, 0) 或 CGRectZero 不是可见的矩形。我还要说 [mainTableView setContentOffset:CGPointZero animated:YES];是更漂亮的表达。
有人注意到在 iOS11 中这一切都被破坏并且在某些情况下无法正确滚动吗?
@PeterLapisu self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true) 似乎适用于 iOS 11
r
rmaddy

注意:此答案对 iOS 11 及更高版本无效。

我更喜欢

[mainTableView setContentOffset:CGPointZero animated:YES];

如果您的表格视图上有一个顶部插图,则必须减去它:

[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];

番茄,番茄。嗯......这在书面上并没有很清楚地表达出来。
当您有表格页眉或页脚视图并希望它们也包含在内时,这是使用的最佳方式。
这确实是一个清晰的代码,但是当您的 tableView 顶部有非零 contentInset 时,它不起作用。例如:tableView.contentInset = UIEdgeInsetsMake(5.0f, 0.0f, 250.0f, 0.0f);。如果是这种情况,在您的代码中,tableView 会滚动到 (0.0f, 5.0f)
我之前评论的解决方案:[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
在 iOS 11 上,您应该考虑改用 -scrollView.adjustedContentInset.top
A
Adrian

可能的行动:

1

func scrollToFirstRow() {
    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

2

func scrollToLastRow() {
    let indexPath = NSIndexPath(forRow: objects.count - 1, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}

3

func scrollToSelectedRow() {
    let selectedRows = self.tableView.indexPathsForSelectedRows
    if let selectedRow = selectedRows?[0] as? NSIndexPath {
        self.tableView.scrollToRowAtIndexPath(selectedRow, atScrollPosition: .Middle, animated: true)
    }
}

4

func scrollToHeader() {
    self.tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
}

5

func scrollToTop(){
    self.tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
}

禁用滚动到顶部:

func disableScrollsToTopPropertyOnAllSubviewsOf(view: UIView) {
    for subview in view.subviews {
        if let scrollView = subview as? UIScrollView {
            (scrollView as UIScrollView).scrollsToTop = false
        }
        self.disableScrollsToTopPropertyOnAllSubviewsOf(subview as UIView)
    }
}

根据需要修改和使用它。

斯威夫特 4

  func scrollToFirstRow() {
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
  }

这就是解决方案,完美 - scrollToFirstRow
优秀的总结。当您有节标题时,您必须使用 option4 scrollToHeader。
有没有办法向上滚动到 Tableview 上方的搜索栏?
K
Kof

最好不要使用 NSIndexPath (空表),也不要假设顶点是 CGPointZero (内容插入),这就是我使用的 -

[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];

希望这可以帮助。


自 iOS 11 起不再有效。
A
Alessandro Ornano

斯威夫特 4:

这很好用:

//self.tableView.reloadData() if you want to use this line remember to put it before 
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)

如果您的 tableView 中有一个 tableHeaderView 并且它是内联的(随内容滚动),则不会
我有一个普通的和一个UITableViewStyleGrouped(标题随内容滚动),这段代码有效。确保您在主线程中并在视图出现后启动此代码 (viewDidAppear)。如果您仍然有问题,请尝试将代码放入:DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: { // the code }
谢谢你。它会带你到第一个牢房。但是,它不显示表格视图标题。
如果 tableView 由于某种原因为空(0 行的 0 部分中没有单元格),这将失败
T
Thanh Pham

在 iOS 11 上,无论通话中状态栏是否可见,都可以使用 adjustedContentInset 正确滚动到顶部。

if (@available(iOS 11.0, *)) {
    [tableView setContentOffset:CGPointMake(0, -tableView.adjustedContentInset.top) animated:YES];
} else {
    [tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:YES];
}

迅速:

if #available(iOS 11.0, *) {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.adjustedContentInset.top), animated: true)
} else {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
}

有时它可能不起作用,除非您将该代码包含在 tableView.beginUpdates() 和 tableView.endUpdates() 中。在此之后,我的卷轴始终有效。
S
ScottyBlades

不要使用

 tableView.setContentOffset(.zero, animated: true)

它有时会不正确地设置偏移量。例如,在我的例子中,单元格实际上略高于带有安全区域插图的视图。不好。

代替使用

 tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)

完美的解决方案。
这些解决方案都不是有效的。第一个在 iOS 11 或更高版本下不起作用。如果表格视图有表格标题或第一部分有部分标题,则第二个不起作用,除非您确实希望第一行位于顶部并且不关心显示任何标题。
@rmaddy 最好的解决方案是什么?
M
MobileMon

我遇到了调用在空 tableView 上尝试某些方法的问题。这是 Swift 4 处理空表视图的另一个选项。

extension UITableView {
  func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
    return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
  }

  func scrollToTop(animated: Bool) {
    let indexPath = IndexPath(row: 0, section: 0)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
      self.scrollToRow(at: indexPath, at: .top, animated: animated)
    }
  }
}

用法:

// from yourViewController or yourTableViewController
tableView.scrollToTop(animated: true)//or false

这不考虑任何表格标题或节标题。
B
Bhavin Bhadani

对于具有 contentInset 的表,将内容偏移设置为 CGPointZero 将不起作用。它会滚动到内容顶部与滚动到桌面。

考虑到内容插入会产生这样的结果:

[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];

谢谢,我一直将它设置为 CGPointZero 并且无法理解为什么会这样。
自 iOS 11 起不再有效。
d
dreamzor

此代码可让您将特定部分滚动到顶部

CGRect cellRect = [tableinstance rectForSection:section];
CGPoint origin = [tableinstacne convertPoint:cellRect.origin 
                                    fromView:<tableistance>];
[tableinstance setContentOffset:CGPointMake(0, origin.y)];

这是最简单的代码,而且运行良好。我实际上放了 CGPointMake(0.0f, 0.0f)。干杯!
此代码对于使部分滚动到顶部非常有用
f
fake girlfriends

斯威夫特 5,iOS 13

我知道这个问题已经有了很多答案,但根据我的经验,这种方法总是有效的:

let last = IndexPath(row: someArray.count - 1, section: 0)
tableView.scrollToRow(at: last, at: .bottom, animated: true)

如果您正在使用动画(如键盘)或某些异步任务,则尤其如此 - 其他答案通常会滚动到几乎底部。如果由于某种原因这并没有让你一直走到底部,那几乎可以肯定是因为一个竞争动画,所以解决方法是将这个动画分派到主队列的末尾:

DispatchQueue.main.async {
    let last = IndexPath(row: self.someArray.count - 1, section: 0)
    self.tableView.scrollToRow(at: last, at: .bottom, animated: true)
}

这似乎是多余的,因为您已经在主队列中,但这并不是因为它序列化了动画。


您还需要检查是否有一个部分
只要您的 tableView 中没有零行,这就会起作用。否则,我建议使用@catlan's answer
@craft 如果您的表格中有零行,那么您不应该尝试滚动到底部,因为它已经在那里了。
@bsod 感谢您的回复。我确实有一个相关的案例。我正在使用节标题但没有行滚动回顶部。另外,我认为问题是关于 top 而不是 bottom
E
Esqarrouth

迅速:

tableView.setContentOffset(CGPointZero, animated: true)

自 iOS 11 起不再有效。
K
Kerim Khasbulatov

斯威夫特 3

tableView.setContentOffset(CGPoint.zero, animated: true)

如果 tableView.setContentOffset 不起作用。

利用:

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()

这对 iOS 11 或更高版本无效。
感谢提及 beginUpdates() 和 endUpdates()
b
budiDino

由于我的 tableView 充满了各种插图,因此这是唯一运作良好的东西:

斯威夫特 3

if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 {
  tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}

斯威夫特 2

if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
  tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}

这对我更有用
很好的答案,不胜感激
o
ocwang

添加到已经说过的内容,您可以创建一个扩展 (Swift) 或类别 (Objective C),以便将来更容易做到这一点:

迅速:

extension UITableView {
    func scrollToTop(animated: Bool) {
        setContentOffset(CGPointZero, animated: animated)
    }
}

任何时候您想将任何给定的 tableView 滚动到顶部,您都可以调用以下代码:

tableView.scrollToTop(animated: true)

自 iOS 11 起不再有效。
j
jacob

我更喜欢以下内容,因为它考虑了插图。如果没有 inset,它仍然会滚动到顶部,因为 inset 将为 0。

tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)

自 iOS 11 起不再有效。
j
jmcastel

斯威夫特:

如果您没有 tableView 标头:

tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

如果是这样 :

tableView.setContentOffset(CGPointMake(0, -tableViewheader.frame.height   + UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

H
Hans Brende

这是我用来在 iOS 11 上正常工作的方法:

extension UIScrollView {
    func scrollToTop(animated: Bool) {
        var offset = contentOffset
        if #available(iOS 11, *) {
            offset.y = -adjustedContentInset.top
        } else {
            offset.y = -contentInset.top
        }
        setContentOffset(offset, animated: animated)
    }
}

d
dengST30

在 Swift 5 中,非常感谢@Adrian 的回答

extension UITableView{

    func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
        return indexPath.section < numberOfSections && indexPath.row < numberOfRows(inSection: indexPath.section)
    }

    func scrollToTop(_ animated: Bool = false) {
        let indexPath = IndexPath(row: 0, section: 0)
        if hasRowAtIndexPath(indexPath: indexPath) {
            scrollToRow(at: indexPath, at: .top, animated: animated)
        }
    }

}

用法:

tableView.scrollToTop()

1. 这在 Swift 4 中也有效。 2. 如果有表头或节头,这不起作用。
G
Gulz

使用 contentOffset 不是正确的方法。这会更好,因为它是表格视图的自然方式

tableView.scrollToRow(at: NSIndexPath.init(row: 0, section: 0) as IndexPath, at: .top, animated: true)

如果有表头或节头,这将不起作用。
j
jimmyruby

这是唯一对我有用的代码片段

斯威夫特 4:

    tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: true)

PS 70 是我的标题和表格视图单元格的高度


这远不是滚动到顶部的正确方法。仅使用三个单独的行来设置内容偏移量是没有意义的。只需要最后一行,但硬编码特定偏移量不是正确的解决方案。
S
Sayali Shinde
func scrollToTop() {
        NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
        [tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

在任何你想要 UITableView 滚动到顶部的地方调用这个函数


S
Shawn

Swift 4 通过扩展,处理空表视图:

extension UITableView {
    func scrollToTop(animated: Bool) {
        self.setContentOffset(CGPoint.zero, animated: animated);
    }
}

这在 iOS 11 中无效。
O
Okan

我使用 tabBarController 并且在每个选项卡的 tableview 中都有几个部分,所以这对我来说是最好的解决方案。

extension UITableView {

    func scrollToTop(){

        for index in 0...numberOfSections - 1 {
            if numberOfSections > 0 && numberOfRows(inSection: index) > 0 {
                scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true)
                break
            }

            if index == numberOfSections - 1 {
                setContentOffset(.zero, animated: true)
                break
            }
        }

    }

}

R
Rohit Gupta

我必须将乘以 -1 * 加到状态栏和导航栏的总和上,因为它会离开屏幕的那个高度,

self.tableView.setContentOffset(CGPointMake(0 , -1 * 
  (self.navigationController!.navigationBar.height +  
  UIApplication.sharedApplication().statusBarFrame.height) ), animated:true)

D
Daniel Galasko

迅速

你的行 = selectioncellRowNumber 你的部分如果你有 = selectionNumber 如果你没有设置为零

//UITableViewScrollPosition.Middle or Bottom or Top

var lastIndex = NSIndexPath(forRow:  selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)

K
Kavin Kumar Arumugam

这是以编程方式将 ScrollTableView 置顶的代码

迅速:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)

J
Jeni Khant

在 Swift-3 中:

self.tableView.setContentOffset(CGPoint.zero, animated: true)

G
Gary

我发现在 iPhone、iPad 和 macCatalyst (macOS) 下强制 UITableViewController 滚动到顶部的最简单方法如下:

准备从 [tableView:numberOfRowsInSection:] 返回 0

调用 [self.tableView reloadData]

调用 [self.tableView layoutIfNeeded]

准备从 [tableView:numberOfRowsInSection:] 返回实际行数

调用 [self.tableView reloadData]


M
Matheus Veloza

如果您想在表格中移动滚动动画,请使用此代码。滚动在 0.5 秒内以动画移动到顶部。

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

[_tableContent scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

[UIView commitAnimations];