How to get height of UITableView when cells are dynamically sized?
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!!!
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:
Set height of table view constraint:
// Class variable heightOfTableViewConstraint set to 1000 heightOfTableViewConstraint = NSLayoutConstraint(item: self.tableView, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .height, multiplier: 0.0, constant: 1000) containerView.addConstraint(heightOfTableViewConstraint)
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. Just Copy Paste the code & it will work.
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
}
}
}
}