Search code examples
iosswiftuitableviewautolayoutuicollectionviewcell

UITableView inside UICollectionViewCell: expand to full size


I'm looking to an approach to implement the layout as shown below:

layout example

Essentially, it consists of the UICollectionViewCell with an instance of UITableView inside it. The UICollectionViewCell contains few other supplementary elements, but those are irrelevant for this question.

I'd like the UITableView to be fully expanded, i.e. show all of the cells. I've chosen UITableView as it has exactly the style I need.

The problem is that the UITableView is not fully expanded. Technically speaking, I'd like the size of the UITableView be equal to its contentSize.

I'm using AutoLayout to calculate UICollectionViewCell size, therefore the "resizable" UITableView would come handy.

So far, I've tried using this approach:

import UIKit

final class FullSizeTableView: UITableView {
    override var intrinsicContentSize: CGSize {
        return contentSize
    }
}

And then using the FullSizeTableView in the UICollectionViewCell: enter image description here

I've constrained the UITableView from all of the 4 sides, at the top to the UIStackView and at the bottom, left and right to the ContentView.

However, the result looks like this:

incorrect result

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4 /// Meanwhile, Returning 4 rows in the DataSource
    }

So, I guess, the AutoLayout doesn't seem to respect the actual size of the UITableView. What could be potential pitfalls that I'm not accounting for?

My goal for the UITableView is to always be fully expanded and shown in full size.

Update1:

Scrolling is already disabled enter image description here


Solution

  • Try using this -

    class ContentSizedTableView: UITableView {
    override var contentSize: CGSize {
        didSet{
            self.invalidateIntrinsicContentSize()
        }
    }
    
    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return contentSize
    }
    
    override func reloadData() {
        super.reloadData()
        invalidateIntrinsicContentSize()
        layoutIfNeeded()
    }
    }