Let's say I have hierarchy like this:
*TableViewCell
**TableView
***TableViewCell
and all of them should be resizable. Did someone face this kind of problem? In past I've used many workarounds like systemLayoutSizeFitting
or precalculation of height in heightForRowAt
, but it always breaks some constraints, because TableViewCell
has height constraint equal to estimated row height and there appear some kinds of magic behavior. Any ways to make this live?
Current workaround:
class SportCenterReviewsTableCell: UITableViewCell, MVVMView {
var tableView: SelfSizedTableView = {
let view = SelfSizedTableView(frame: .zero)
view.clipsToBounds = true
view.tableFooterView = UIView()
view.separatorStyle = .none
view.isScrollEnabled = false
view.showsVerticalScrollIndicator = false
view.estimatedRowHeight = 0
if #available(iOS 11.0, *) {
view.contentInsetAdjustmentBehavior = .never
} else {
// Fallback on earlier versions
}
return view
}()
private func markup() {
contentView.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.register(ReviewsTableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.snp.makeConstraints() { make in
make.top.equalTo(seeAllButton.snp.bottom).offset(12)
make.left.equalTo(contentView.snp.left)
make.right.equalTo(contentView.snp.right)
make.bottom.lessThanOrEqualTo(contentView.snp.bottom)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ReviewsTableViewCell
cell.viewModel = viewModel.cellViewModels[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ReviewsTableViewCell
cell.viewModel = viewModel.cellViewModels[indexPath.row]
cell.setNeedsLayout()
cell.layoutIfNeeded()
let size = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)
return size.height
}
}
Self sizing tableView class:
class SelfSizedTableView: UITableView {
override func reloadData() {
super.reloadData()
self.invalidateIntrinsicContentSize()
self.layoutIfNeeded()
}
override var intrinsicContentSize: CGSize {
self.setNeedsLayout()
self.layoutIfNeeded()
return contentSize
}
}
contentSize
of cells withautomaticDimension
are equal toestimatedRowHeight
, it would be settingtableView
height =estimatedRowHeight
*numberOfRows
. – Derekworkaround()
function we should go throughforeach()
, because you just do the same thingn
times. However, it works properly. Explanation with better precision would be appreciated! – Derekn
is not required number of operation, it becomes resized properly afterrandom
number of operation. Am I right? – Derek