UITableViewCell with autolayout left margin different on iPhone and iPad

 How to fix it

After fighting with the apple bug reporting team with many sample projects and screenshots and dissecting that answer, I’ve found that the solution to have your custom-style cells behave consistently regarding their margins and be just like the default UITableViewCells, you have to do the following (mostly based on Becky’s answer, I’ve highlighted what’s different and what made it work for me) :

  1. Select your cell’s content view in IB

  2. Go to the Size Inspector

  3. In the Layout Margins section, check Preserve Superview Margins (do not click the plus-sign)

    Checking preserve superview margins

  4. (And here’s the key) Do the same for the cell itself (the content view’s parent if you will)

    The cell and not the content view this time

  5. Setup your constraints as follows : Label.Leading = Superview.Leading Margin (with a constant of 0)

    Setting the constraint for the custom cell's label

Now all your cells will have their label consistent with the default cells! This works for me in Xcode 7 and up and it includes the fix mentioned in the thread I referred to. IB and the simulator should now show properly aligned labels.

Final result in the simulator

You could also do some of this programmatically, for example in the View Controller’s class :

cell.preservesSuperviewLayoutMargins = true
cell.contentView.preservesSuperviewLayoutMargins = true

Or you could have it set up by calling UIAppearance once at startup (I only know Swift, sorry) :

UITableViewCell.appearance().preservesSuperviewLayoutMargins = true
UITableViewCell.appearance().contentView.preservesSuperviewLayoutMargins = true

How and why it works

As Ethan kindly pointed out, Apple’s own documentation on UIView describes preservesSuperviewLayoutMargins as follows :

When the value of this property is true, the superview’s margins are also considered when laying out content. This margin affects layouts where the distance between the edge of a view and its superview is smaller than the corresponding margin. For example, you might have a content view whose frame precisely matches the bounds of its superview. When any of the superview’s margins is inside the area represented by the content view and its own margins, UIKit adjusts the content view’s layout to respect the superview’s margins. The amount of the adjustment is the smallest amount needed to ensure that content is also inside the superview’s margins.

Therefore, if you want your cell’s content to align with the TableView’s margins (it’s great-grandparent if you will), you need to have your content’s two ascendants, Content View and the Table Cell itself, preserve the margins of their own superview.

Why this isn’t default behavior surprises me : I feel like most developers who don’t want to customize everything would expect this “inheritance” by default.

Leave a Comment