How to scroll to the exact end of the UITableView?

前端 未结 16 2517
天涯浪人
天涯浪人 2020-12-07 18:48

I have a UITableView that is populated with cells with dynamic height. I would like the table to scroll to the bottom when the view controller is pushed from vi

16条回答
  •  独厮守ぢ
    2020-12-07 19:11

    [Swift 3, iOS 10]

    I've ended up using kind-of-hacky solution, but it doesn't depend on rows indexpaths (which leads to crashes sometimes), cells dynamic height or table reload event, so it seems pretty universal and in practice works more reliable than others I've found.

    • use KVO to track table's contentOffset

    • fire scroll event inside KVO observer

    • schedule scroll invocation using delayed Timer to filter multiple
      observer triggers

    The code inside some ViewController:

    private var scrollTimer: Timer?
    private var ObserveContext: Int = 0
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        table.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.new, context: &ObserveContext)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        table.removeObserver(self, forKeyPath: "contentSize")
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if (context == &ObserveContext) {
            self.scheduleScrollToBottom()
        }
    }
    
    func scheduleScrollToBottom() {
    
        if (self.scrollTimer == nil) {
            self.scrollTimer = Timer(timeInterval: 0.5, repeats: false, block: { [weak self] (timer) in
                let table = self!.table
    
                let bottomOffset = table.contentSize.height - table.bounds.size.height
                if !table.isDragging && bottomOffset > 0 {
                    let point: CGPoint = CGPoint(x: 0, y: bottomOffset)
                    table.setContentOffset(point, animated: true)
                }
    
                timer.invalidate()
                self?.scrollTimer = nil
            })
            self.scrollTimer?.fire()
        }
    }
    

提交回复
热议问题