How to scroll to the exact end of the UITableView?

前端 未结 16 2561
天涯浪人
天涯浪人 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:18

    I tried Umair's approach, however in UITableViews, sometimes there can be a section with 0 rows; in which case, the code points to an invalid index path (row 0 of an empty section is not a row).

    Blindly minusing 1 from the number of rows/sections can be another pain point, as, again, the row/section could contain 0 elements.

    Here's my solution to scrolling to the bottom-most cell, ensuring the index path is valid:

    extension UITableView {
        func scrollToBottomRow() {
            DispatchQueue.main.async {
                guard self.numberOfSections > 0 else { return }
    
                // Make an attempt to use the bottom-most section with at least one row
                var section = max(self.numberOfSections - 1, 0)
                var row = max(self.numberOfRows(inSection: section) - 1, 0)
                var indexPath = IndexPath(row: row, section: section)
    
                // Ensure the index path is valid, otherwise use the section above (sections can
                // contain 0 rows which leads to an invalid index path)
                while !self.indexPathIsValid(indexPath) {
                    section = max(section - 1, 0)
                    row = max(self.numberOfRows(inSection: section) - 1, 0)
                    indexPath = IndexPath(row: row, section: section)
    
                    // If we're down to the last section, attempt to use the first row
                    if indexPath.section == 0 {
                        indexPath = IndexPath(row: 0, section: 0)
                        break
                    }
                }
    
                // In the case that [0, 0] is valid (perhaps no data source?), ensure we don't encounter an
                // exception here
                guard self.indexPathIsValid(indexPath) else { return }
    
                self.scrollToRow(at: indexPath, at: .bottom, animated: true)
            }
        }
    
        func indexPathIsValid(_ indexPath: IndexPath) -> Bool {
            let section = indexPath.section
            let row = indexPath.row
            return section < self.numberOfSections && row < self.numberOfRows(inSection: section)
        }
    }
    

提交回复
热议问题