How to get height of UITableView when cells are dynamically sized? How to get height of UITableView when cells are dynamically sized? ios ios

How to get height of UITableView when cells are dynamically sized?


I finally hacked out a solution:

tableView.contentSize.height will not work for dynamic cells because they will only return the number of cells * estimatedRowHeight.

Hence, to get the dynamic table view height, you look for all visible cells, and sum up their heights. Note that this only works for table views that are shorter than your screen.

However, before we do the above to look for visible cells, it is important to know that note we need to get the table view on the screen so that we can obtain visible cells. To do so, we can set a height constraint for the table view to some arbitrarily large number just so it appears on the screen:

  1. Set height of table view constraint:

    // Class variable heightOfTableViewConstraint set to 1000heightOfTableViewConstraint = NSLayoutConstraint(item: self.tableView, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .height, multiplier: 0.0, constant: 1000)containerView.addConstraint(heightOfTableViewConstraint)
  2. Call tableView.layoutIfNeeded(), and when completed, look for the visible cells, sum up their height, and edit the heightOfTableViewConstraint:

    UIView.animate(withDuration: 0, animations: {    self.tableView.layoutIfNeeded()    }) { (complete) in        var heightOfTableView: CGFloat = 0.0        // Get visible cells and sum up their heights        let cells = self.tableView.visibleCells        for cell in cells {            heightOfTableView += cell.frame.height        }        // Edit heightOfTableViewConstraint's constant to update height of table view        self.heightOfTableViewConstraint.constant = heightOfTableView}


Above mentioned solutions are pretty well. I tried a different approach & its smooth & clear to understand

override func viewDidLoad() {    super.viewDidLoad()    tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)}override func viewWillDisappear(_ animated: Bool) {    tableView.removeObserver(self, forKeyPath: "contentSize")}override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {        if keyPath == "contentSize"{            if object is UITableView{                if let newValue = change?[.newKey]{                    let newSize = newValue as! CGSize                    heightOfTableViewConstraint.constant = newSize.height                }            }        }    }


it's already been answered, but I want to share my experience as well.

I have the same problem. I've searched answers in many similar questions and tried their answers and doesn't work.

Finally I've found leonardloo answer. Thanks a lot, but it doesn't solved my problem yet. I just want to complete his answer. I put this code from his answer:

UIView.animate(withDuration: 0, animations: {self.tableView.layoutIfNeeded()}) { (complete) in    var heightOfTableView: CGFloat = 0.0    // Get visible cells and sum up their heights    let cells = self.tableView.visibleCells    for cell in cells {        heightOfTableView += cell.frame.height    }    // Edit heightOfTableViewConstraint's constant to update height of table view    self.heightOfTableViewConstraint.constant = heightOfTableView}

in this block of code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {    ...    if indexPath.row == data.count-1{         // Insert the code here    }    return cell}

It means after all the rows in table have been loaded, we update the height of the row using that piece of code.It works!!!