iOS
How to Create Dynamic Height TableView Inside a TableViewCell in iOS using Swift

How to Create Dynamic Height TableView Inside a TableViewCell in iOS using Swift

When designing a complex UI in iOS, there may be cases where you need to display a table view inside another table view cell, where the height of the inner table view needs to be dynamic. This can be achieved by using a custom subclass of UITableView for the inner table view and configuring it to automatically adjust its height based on its content.

Let’s start by creating a custom subclass of UITableView called SubTableView:

class SubTableView: UITableView {
    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return self.contentSize
    }

    override var contentSize: CGSize {
        didSet{
            self.invalidateIntrinsicContentSize()
        }
    }

    override func reloadData() {
        super.reloadData()
        self.invalidateIntrinsicContentSize()
    }
}

The intrinsicContentSize property returns the size that best fits the table view’s content, which is determined by calling layoutIfNeeded() to force the table view to lay out its cells, and returning the contentSize property. The contentSize property is observed using didSet, and the invalidateIntrinsicContentSize() method is called to notify the system that the intrinsic content size has changed. Finally, the reloadData() method is overridden to call invalidateIntrinsicContentSize() after reloading the data.

Next, let’s create the table view cell that contains the inner table view. We’ll call it ParentTVCell:

class ParentTVCell: UITableViewCell {
    // ⭐️⭐️⭐️ this is important
    @IBOutlet weak var subTableView: SubTableView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        initialSetup()
    }
    
}

extension ParentTVCell {
    private func initialSetup() {
        // Set the estimated row height for the inner table view
        // ⭐️⭐️⭐️ This is important else it wont work.
        subTableView.estimatedRowHeight = 44.0
    }
}

//MARK: - TableView protocols

extension ParentTVCell: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // Handle cell selection if needed
    }
}

extension ParentTVCell: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number of rows in the inner table view
        return 4
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: ChildTVCell = tableView.smDequeueReusableCell(forIndexPath: indexPath)
        return cell
    }
    
}

In the awakeFromNib() method of ParentTVCell, we call initialSetup() to perform some initial configuration. In initialViewSetup(), we set the estimatedRowHeight property of the inner table view to 44.0, or any other value that suits your needs.

The ParentTVCell class adopts the UITableViewDelegate and UITableViewDataSource protocols to provide data and handle events for the inner table view. In tableView(_:numberOfRowsInSection:), we return the number of rows in the inner table view, and in tableView(_:cellForRowAt:), we dequeue and return a ChildTVCell, or any other custom cell type you’ve defined.

Finally, in tableView(_:heightForRowAt:), we return UITableView.automaticDimension to tell the system to automatically determine the height of the inner table view cells based on their content.

In conclusion, displaying a dynamic-height table view inside a table view cell is a useful feature that can enhance the user experience in certain cases. By using a custom table view subclass and implementing the necessary delegate and data source methods, it’s possible to achieve this functionality with ease.

In this tutorial, we demonstrated how to create a SubTableView class that can be used to display a dynamic-height table view inside a table view cell. We also provided a sample implementation of a parent table view cell that uses the SubTableView class to display a list of child items.

Remember that this approach may not be suitable for every use case, and you should carefully consider the performance implications before implementing it. However, if you need to display a dynamic-height table view inside a table view cell, this tutorial should provide you with a good starting point.

I hope this tutorial was helpful, and feel free to customize the code to suit your specific needs. Happy coding!

Leave a Reply