I have a custom cell class (TripMatrixCell) with a variable of tripMatrixViewController.
class TripMatrixCell: UITableViewCell {
var tripMatrixViewController: TripMatrixViewController! {
didSet {
contentView.addSubview(tripMatrixViewController.view)
tripMatrixViewController.view.pinToSuperview()
}
}
}
The tripMatrixViewController is a UIViewController with a custom tableView containing other custom cells (TwoColumnCondensedTripCell). Here is the custom tableView class which will house the TwoColumnCondensedTripCells:
final class ContentSizedTableView: UITableView {
override var contentSize: CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
invalidateIntrinsicContentSize()
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
This tableView is set up here, in the TripMatrixViewController:
override public func viewDidLoad() {
super.viewDidLoad()
bind()
}
func bind() {
tableView = ContentSizedTableView(frame: view.frame, style: .plain)
tableView.delegate = self
tableView.dataSource = self
view.addSubview(tableView)
tableView.pinToSuperview()
tableView.register(TwoColumnCondensedTripCell.nib, forCellReuseIdentifier: TwoColumnCondensedTripCell.reuseIdentifier)
tableView.tableHeaderView = UIView(frame: CGRect.zero)
tableView.tableFooterView = UIView(frame: CGRect.zero)
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.estimatedRowHeight = 167.0
tableView.rowHeight = UITableView.automaticDimension
tableView.clipsToBounds = false
tableView.isScrollEnabled = allowsScrolling
}
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Whenever the TripMatrixCells' tripMatrixViewController variable is set, its view (which contains the custom tableView with rows of TwoColumnCondensedTripCells) is added as a subview of the cell's contentView and is then pinnedToSuperview. Here is the pinToSuperview method:
func pinToSuperview() {
if let superview = superview {
self.pinToView(superview)
}
}
func pinToView(_ view: UIView) {
self.translatesAutoresizingMaskIntoConstraints = false
self.pinToView(view, insets: UIEdgeInsets.zero)
}
func pinToView(_ view: UIView, insets: UIEdgeInsets) {
self.translatesAutoresizingMaskIntoConstraints = false
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: insets.top))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: -insets.bottom))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1.0, constant: insets.left))
superview?.addConstraint(NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: view, attribute: .right, multiplier: 1.0, constant: -insets.right))
}
I try to populate a UITableView with this TripMatrixCell, however, the height for the row which contains this TripMatrixCell is not accurate and the bottom of the cell is being cut off. In the screenshot below, the TripMatrixCell has a black background, and its subviews (the TwoColumnCondensedTripCells) are represented by the white rectangles, of which the bottom two are being cut off due to the row height not being correctly calculated.
Here are the methods which set up the tableView that attempts to display the TripMatrixCell:
override public func viewDidLoad() {
super.viewDidLoad()
bind()
refreshControl = refreshController?.refreshControl
refreshController?.refresh()
}
func bind() {
tableView = UITableView(frame: view.frame, style: .grouped)
tableView.pinToSuperview()
tableView.register(TripMatrixCell.nib, forCellReuseIdentifier: TripMatrixCell.reuseIdentifier)
tableView.tableFooterView = UIView()
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.estimatedRowHeight = 167.0
tableView.rowHeight = UITableView.automaticDimension
}
override public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
I can get the cell's height to load properly if I call tableView.beginUpdates() and tableView.endUpdates() in viewDidAppear, but the problem with that is that the user can then see the update happening.
How can I get the cell's height to be properly accounted for in the first pass? I've gone through a dozen different posts and articles looking for a solution and nothing I've implemented so far has worked. I hope I laid things out clearly without adding too much unnecessary code. If not, I'm ready to provide more info if needed. I've already spent a dozen+ hours trying to resolve this and appreciate any help!