UITableView:如何从底部滚动(如对话列表)?

UITableView: how to scroll from bottom (like a conversation list)?

我想使用 UITableView 创建一个列表,使行从底部开始显示,就像对话列表(例如 Messenger)一样。

我尝试了一个使用 header 高度的基本示例(这将根据其内容大小占用 table 视图的剩余高度)。这是我写的:

class ViewController: UIViewController {
    var headerHeight: CGFloat {
        tableView.bounds.size.height - tableView.contentSize.height
    }
    // MARK: Instance Properties
    var heights: [CGFloat] = []
    
    // MARK: Table Properties
    @IBOutlet weak var tableView: UITableView!
    
    @IBAction func add() {
        heights.append(CGFloat(arc4random_uniform(200)))
        tableView.reloadData()
        DispatchQueue.main.async {
            self.tableView.scrollToRow(at: IndexPath(row: self.heights.count - 1, section: 0),
                                       at: .bottom,
                                       animated: true)
        }
    }
    
    // MARK: Init
    init() {
        super.init(nibName: "ViewController", bundle: .main)
    }
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    // MARK: Life
    override func viewDidLoad() {
        view.backgroundColor = .white
        tableView.register(UINib(nibName: ViewControllerCell.reuseIdentifier, bundle: .main),
                           forCellReuseIdentifier: ViewControllerCell.reuseIdentifier)
    }
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let v = UIView(frame: CGRect(origin: .zero,
                                     size: CGSize(width: tableView.frame.size.width, height: headerHeight)))
        v.backgroundColor = .red
        return v
    }
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        headerHeight
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let v = UIView(frame: .zero)
        v.backgroundColor = .clear
        return v
    }
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        .leastNormalMagnitude
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        heights.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: ViewControllerCell.reuseIdentifier, for: indexPath) as! ViewControllerCell
        cell.constraint.constant = heights[indexPath.row]
        return cell
    }
}

class ViewControllerCell: UITableViewCell {
    static let reuseIdentifier = "ViewControllerCell"
    // constraint sets a random height for the cell
    @IBOutlet weak var constraint: NSLayoutConstraint!
}

我将 header 视图背景设置为红色,以便在此示例中准确地看到它。但出于某种原因,这只能在两次中起作用:

你能帮帮我吗?谢谢!

一个简单且常见的解决方案是翻转 UITableView(围绕 Y 轴)。在您设置 UITableView 的位置或 viewDidLoad 中执行:

tableView.transform = CGAffineTransform(scaleX: 1, y: -1)

并且在您的 cellForRowAt 或自定义单元格设置中:

cell.transform = CGAffineTransform(scaleX: 1, y: -1)