tl;dr How can I get correct the height of my tableView after cell height changes made due to cell expansion——without using delays?
My tableViewcells, expand and collapse. Because of that I need to pass (using a delegate method) the tableView's height to it's superView. It's superview is a collectionviewcell.
extension ArtistDetailViewController: UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? WorkTableViewCell else {
fatalError()
}
//1: create model
var work = works[indexPath.row]
//2: update the model
work.isExpanded = !work.isExpanded
//3: upadte dataSource
works[indexPath.row] = work
//4: update the text of textView
cell.moreInfoTextView.text = work.isExpanded ? work.info : WorkTableViewCell.textViewText
cell.moreInfoTextView.textAlignment = work.isExpanded ? .left : .center
//5: update TableView
tableView.beginUpdates()
tableView.endUpdates()
tableView.scrollToRow(at: indexPath, at: .top, animated: true)
//6: slavishly update cell with everything you got!
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
cell.contentView.setNeedsUpdateConstraints()
cell.contentView.updateConstraintsIfNeeded()
cell.contentView.setNeedsLayout()
cell.contentView.layoutIfNeeded()
print(tableView.contentSize.height) // prints 252
//7: pass tableView height with delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01, execute: {
print(tableView.contentSize.height) // prints 341
self.tableViewHeight = tableView.contentSize.height
self.delegate?.didRender(with: self.tableViewHeight)
})
}
}
my ArtistDetailViewController
has a tableView property.
The tableView property subclassed from a tableView which has intrinsicSize.
class AutomaticHeightTableView: UITableView {
override var intrinsicContentSize: CGSize {
return contentSize
}
override func reloadData() {
super.reloadData()
invalidateIntrinsicContentSize()
}
}
The problem I have is if I don't use any delay (step 7) is:
- The tableView's height would be enlarged enough ie it would enlarge, but just not enlarge enough.
- The tableView won't collapse later.
- Even if I do use delay sometimes it won't collapse/expand \o/
Obviously the problem is that these updates are done in an async manner and the the value is calculated too quick! As for proof:
If you saw the prints, The height of the tableView changes from 252 to 341—after the delay.
In my step 6 I tried adding all sorts of updates so that I could avoid adding a delay but that didn't work.
The result with delay:
The result without delay: