Self-sizing table view cells have been around a long time but are still a regular source of confusion. Interface Builder added to the confusion by not automatically sizing the cells in the canvas. That’s finally fixed in Xcode 11!
What’s The Problem?
To recap, a “self-sizing” table view cell should adjust its height to fit the content of the cell at its natural height. To create one follow these rules when laying out the cell:
- Add your subviews to the content view of the table view cell.
- Add constraints to fully constrain, vertically and horizontally, your subviews to the content view (not the cell itself).
- Set the table view height to “Automatic”.
- Set a non-zero value for the estimated row height (or use “Automatic”).
Doing this in Interface Builder should be straightforward. The table view row height and estimated row height both default to “Automatic”:
The prototype cell in Interface Builder doesn’t give you a lot of room to work with. I usually find it best to drag the bottom of the cell down to make some space. Here I’ve made it 100 points high:
I’ve added a text view with a several lines of placeholder text. The text view has scrolling disabled and is using the
.body text style. I added four constraints to pin it to the margins of the content view:
At this point we have a valid layout that is self-sizing when I run it but Interface Builder is none the wiser. It continues to show the cell as being 100 points high truncating most of the text view.
You can see the fixed size the cell takes in the canvas if you select the cell (not the table view) and look in the size inspector. This is what Xcode 10 would show:
Note that changing this row height only changes the height of the cell in Interface Builder - it doesn’t change the row height at runtime. If you unclick the “Custom” checkbox the row height goes back to the default:
Either way, Xcode 10 never shows the table view cell at the correct size for the placeholder content:
Better Late Than Never…
Here’s the good news buried in the Xcode 11 release notes:
Cells in a UITableView can now self size with Auto Layout constrained views in the canvas. To opt into the behavior for existing table views, enable “Automatic” for the table view estimated item size, and “Automatic” for cell’s height in the Size inspector. (35735970)
Assuming you have switched to Xcode 11, this is how the size inspector looks for the table view cell:
Note the “Automatic” checkbox. If you select it Interface Builder wakes up and realizes you have created a self-sizing cell (you can just about read the actual row height of 346.5 points):
The table view cell in the canvas is finally self-sizing:
If you change the text style of the text view the cell resizes in the canvas to take into account the new content size:
Note that anytime you manually change the row height of the cell in the canvas it disables the “Automatic” setting in the size inspector.
I’ve no idea why the Xcode engineers suddenly decided to fix this in Xcode 11. It’s not the only example of some dusty corners of Interface Builder getting some polish. See also:
It would appear that not everybody is working on SwiftUI yet. Truly a case of better late than never…
If you’re still struggling with Auto Layout and self-sizing table view cells you might like my book: