If you are looking for a way to put a collection view inside a table cell without manually calculating table row heights, you are in the right place.
If your app target is iOS 14, you might consider using UICollectionLayoutListConfiguration to construct sections of the collection view as lists like in table views. Here is a WWDC-20 video showing how to do that.
This piece was written when iOS 14 just came out. Many apps still target iOS 13 or earlier. This method is for those apps.
This Github repository contains the complete project: https://github.com/viettran/CollectionViewTableCell. You can clone it to follow along. Below are step-by-step instructions and technical explanations.
Building The Basic
Step 1: Create a custom UITableViewCell to host the collection view.
There is no special setup for this table cell. I would just use XCode to add a new Cocoa Touch class, subclass UITableViewCell and also create XIB file.
Step 2: Put your collection view, if you already have one, in the
CollectionViewTableViewCell. If you don’t already have a collection view, create one. In my sample codes, I use
UICollectionViewController. However, you can use
UIViewController with a custom
UICollectionView, if preferred.
Step 3: Put the
CollectionViewTableViewCell in your table view if you already have one. If not, create your table view. Also setup your table view to use automatic row height.
Step 4: Setup a callback when collection view is done laying out.
If you are thinking about using
systemLayoutSizeFitting, it won’t work. Simply because the table view fetches those information before the collection view layouts its subviews. You would have to manually calculate the collection view size. This method, however, is about self sizing - relying on the collection view to layout its subviews.
Step 5: Hook up
didLayoutAction in table view cell.
Step 6: Override
There are a lot of confusions/discussions/arguments between
sizeThatFits). For me, I only use
intrinsicContentSize when the view is a leaf in the view hierarchy, like labels or buttons. For views with subviews, I always use
systemLayoutSizeFitting. By the way, in this case,
intrinsicContentSize won’t work.
The table view, when calculating row height in
automaticDimension, will call this method
I want the collection view to entirely vertically expand without scrolling so I used its
UICollectionView is a
Updating table layout without reloading row
Step 7: Useful extensions.
I want to emphasize this part because it’s easily overlooked. Don’t
reloadRows while you only want to update table layout. All you need to do is to call
endUpdates(). If you don’t want animation, you can wrap it in
To make the logic contained in
UITableViewCell, we need to be able to access the
tableView from the cell. Thus, I created some extensions as below.
Step 8: Update row height.
Now it’s time to implement the callback when the collection view is done laying out: update table view layout.
That’s it! Let me know if you have any feedback. Again, here is the entire code: https://github.com/viettran/CollectionViewTableCell