0

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.

enter image description here

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!

  • Does this answer your question? [Is it possible to implement tableview inside tableview cell in swift 3?](https://stackoverflow.com/questions/46674808/is-it-possible-to-implement-tableview-inside-tableview-cell-in-swift-3) – Nirmit Dagly May 18 '21 at 01:52
  • Possible duplicate of https://stackoverflow.com/questions/46674808/is-it-possible-to-implement-tableview-inside-tableview-cell-in-swift-3 https://stackoverflow.com/questions/35852405/create-tableview-inside-tableviewcell-using-swift – Nirmit Dagly May 18 '21 at 01:52
  • @NirmitDagly Unfortunately it does not. I'm already implementing that solution but it doesn't solve the problem I'm experiencing. – michaelthedeveloper May 18 '21 at 15:16

0 Answers0