ios 如何在视图出现之前滚动到 iPhone 上 UITableView 的底部

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2770158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:11:28  来源:igfitidea点击:

How to scroll to the bottom of a UITableView on the iPhone before the view appears

iosobjective-ccocoa-touchuitableview

提问by acqu13sce

I have a UITableViewthat is populated with cells of a variable height. I would like the table to scroll to the bottom when the view is pushed into view.

我有一个UITableView填充了可变高度的单元格。当视图被推入视图时,我希望表格滚动到底部。

I currently have the following function

我目前有以下功能

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0];
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];

log is a mutable array containing the objects that make up the content of each cell.

log 是一个可变数组,其中包含构成每个单元格内容的对象。

The above code works fine in viewDidAppearhowever this has the unfortunate side effect of displaying the top of the table when the view first appears and then jumping to the bottom. I would prefer it if the table viewcould be scrolled to the bottom before it appears.

上面的代码工作正常,viewDidAppear但是这有一个不幸的副作用,当视图第一次出现时显示表格的顶部,然后跳到底部。如果table view可以在它出现之前滚动到底部,我会更喜欢它。

I tried the scroll in viewWillAppearand viewDidLoadbut in both cases the data has not been loaded into the table yet and both throw an exception.

我试图滚动中viewWillAppearviewDidLoad,但在这两种情况下的数据没有被加载到表并且都抛出异常。

Any guidance would be much appreciated, even if it's just a case of telling me what I have is all that is possible.

任何指导都将不胜感激,即使只是告诉我我所拥有的一切都是可能的。

回答by Jacob Relkin

I believe that calling

我相信呼唤

 tableView.setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude), animated: false)

will do what you want.

会做你想做的。

回答by Chamira Fernando

I think the easiest way is this:

我认为最简单的方法是这样的:

if (self.messages.count > 0)
{
    [self.tableView 
        scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 
        inSection:0] 
        atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

Swift 3 Version:

斯威夫特 3 版本:

if messages.count > 0 {
    userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true)
}

回答by Osama F Elias

From Jacob's answer, this is the code:

雅各布的回答,这是代码:

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

    if (self.messagesTableView.contentSize.height > self.messagesTableView.frame.size.height) 
    {
        CGPoint offset = CGPointMake(0, self.messagesTableView.contentSize.height - self.messagesTableView.frame.size.height);
        [self.messagesTableView setContentOffset:offset animated:YES];
    }
}

回答by Hans One

If you need to scroll to the EXACT end of the content, you can do it like this:

如果您需要滚动到内容的 EXACT 结尾,您可以这样做:

- (void)scrollToBottom
{
    CGFloat yOffset = 0;

    if (self.tableView.contentSize.height > self.tableView.bounds.size.height) {
        yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height;
    }

    [self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO];
}

回答by RaffAl

I'm using autolayout and none of the answers worked for me. Here is my solution that finally worked:

我正在使用自动布局,但没有一个答案对我有用。这是我最终奏效的解决方案:

@property (nonatomic, assign) BOOL shouldScrollToLastRow;


- (void)viewDidLoad {
    [super viewDidLoad];

    _shouldScrollToLastRow = YES;
}


- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    // Scroll table view to the last row
    if (_shouldScrollToLastRow)
    {
        _shouldScrollToLastRow = NO;
        [self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
    }
}

回答by Ryan Herubin

Here's an extension that I implemented in Swift 2.0. These functions should be called after the tableviewhas been loaded:

这是我在 Swift 2.0 中实现的扩展。这些函数应tableview在加载后调用:

import UIKit

extension UITableView {
    func setOffsetToBottom(animated: Bool) {
        self.setContentOffset(CGPointMake(0, self.contentSize.height - self.frame.size.height), animated: true)
    }

    func scrollToLastRow(animated: Bool) {
        if self.numberOfRowsInSection(0) > 0 {
            self.scrollToRowAtIndexPath(NSIndexPath(forRow: self.numberOfRowsInSection(0) - 1, inSection: 0), atScrollPosition: .Bottom, animated: animated)
        }
    }
}

回答by ma11hew28

The accepted solution by @JacobRelkindidn't work for me in iOS 7.0 using Auto Layout.

通过@JacobRelkin接受的解决方案并没有为我在的iOS 7.0中使用自动布局工作。

I have a custom subclass of UIViewControllerand added an instance variable _tableViewas a subview of its view. I positioned _tableViewusing Auto Layout. I tried calling this method at the end of viewDidLoadand even in viewWillAppear:. Neither worked.

我有一个自定义子类,UIViewController并添加了一个实例变量_tableView作为其view. 我_tableView使用自动布局定位。我尝试viewDidLoadviewWillAppear:. 都没有工作。

So, I added the following method to my custom subclass of UIViewController.

因此,我将以下方法添加到我的自定义子类UIViewController.

- (void)tableViewScrollToBottomAnimated:(BOOL)animated {
    NSInteger numberOfRows = [_tableView numberOfRowsInSection:0];
    if (numberOfRows) {
        [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
    }
}

Calling [self tableViewScrollToBottomAnimated:NO]at the end of viewDidLoadworks. Unfortunately, it also causes tableView:heightForRowAtIndexPath:to get called three times for every cell.

工作[self tableViewScrollToBottomAnimated:NO]结束时调用viewDidLoad。不幸的是,它也会导致tableView:heightForRowAtIndexPath:每个单元格被调用 3 次。

回答by Vasily Bodnarchuk

Details

细节

  • Xcode 8.3.2, swift 3.1
  • Xcode 10.2 (10E125), Swift 5
  • Xcode 8.3.2,快速 3.1
  • Xcode 10.2 (10E125),Swift 5

Code

代码

import UIKit

extension UITableView {
    func scrollToBottom(animated: Bool) {
        let y = contentSize.height - frame.size.height
        if y < 0 { return }
        setContentOffset(CGPoint(x: 0, y: y), animated: animated)
    }
}

Usage

用法

tableView.scrollToBottom(animated: true)

Full sample

完整样品

Do not forget to paste solution code!

不要忘记粘贴解决方案代码!

import UIKit

class ViewController: UIViewController {

    private weak var tableView: UITableView?
    private lazy var cellReuseIdentifier = "CellReuseIdentifier"

    override func viewDidLoad() {
        super.viewDidLoad()
        let tableView = UITableView(frame: view.frame)
        view.addSubview(tableView)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
        self.tableView = tableView
        tableView.dataSource = self
        tableView.performBatchUpdates(nil) { [weak self] result in
            if result { self?.tableView?.scrollToBottom(animated: true) }
        }
    }
}

extension ViewController: UITableViewDataSource {

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath )
        cell.textLabel?.text = "\(indexPath)"
        return cell
    }
}

回答by XcodeNOOB

Actually a "Swifter" way to do it in swift is :

实际上,在 swift 中执行此操作的“更快”方法是:

var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0)
self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)

work Perfect for me.

非常适合我。

回答by Segev

For Swift:

对于斯威夫特:

if tableView.contentSize.height > tableView.frame.size.height {
    let offset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.size.height)
    tableView.setContentOffset(offset, animated: false)
}