Frederik A. Winkelsdorf Frederik A. Winkelsdorf - 8 months ago 27
Swift Question

UILabel Autolayout ignores UITableViewCell's left margin on iOS 8.1 and 8.2

I need to support iOS 8.1 and 8.2 but I can't remember how to get the layoutMargins right, already search a lot (in my own old Projecs, Google, SO, OpenRadar).

Starting with iOS 8.3 everything works as expected.

Can anybody please point me in the right direction?

For the custom Cell and it's contentView I set "Preserve Superview Margins" in IB. "Follow Readable Width" (iOS9) is off.

Testing on iPad Air 2 Simulator.

iOS 8.1 and 8.2 (too small left margin of UILabel):

enter image description here

iOS 8.3 to 9.3 (correct):

enter image description here

AutoLayout as usual, to contentView (just added top/bottom +3px):

enter image description here

Tried to check the layoutMargins by Code (in this Cell class), but they are correct.

Here is the full cell class:

class TextLabelTableViewCell: UITableViewCell {

@IBOutlet weak var customTextLabel: UILabel!

override func awakeFromNib() {
// Initialization code

func configure(text: String?) {
customTextLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)

customTextLabel.text = text
customTextLabel.accessibilityLabel = text

override func layoutSubviews() {

debugPrint("layoutMargins: ", layoutMargins)
debugPrint("contentView.layoutMargins: ", contentView.layoutMargins)
debugPrint("separatorInsets: ", separatorInset)
"layoutMargins: " __C.UIEdgeInsets(top: 8.0, left: 16.0, bottom: 8.0, right: 16.0) - 8, 16, 8, 16
"contentView.layoutMargins: " __C.UIEdgeInsets(top: 8.0, left: 16.0, bottom: 8.0, right: 16.0) - 8, 16, 8, 16
"separatorInsets: " __C.UIEdgeInsets(top: 0.0, left: 16.0, bottom: 0.0, right: 0.0) - 0, 16, 0, 0


Checked the Cell in Reveal. Everything is correct, except the UILabel. Here's a screenshot from the Label inside the above Cell. Frame X should be 16.

enter image description here

Found this thread: UITableViewCell with autolayout left margin different on iPhone and iPad

Interesting is this comment to the 1st and accepted answer:

So I tried it on the 8.1 simulator and indeed, the margins are too
narrow, meaning that the superview's layout margins are not
preserved... However this is a bug that Apple has fixed in 8.3 and
somehow fixed again in iOS 9. – Jonas Zaugg

Ok, that this is a bug is obvious. But how do you usually workaround? That's what I forgot. Setting each and every inset for both layoutMargin and separatorInsets manually for 8.0 to 8.2 (UIAppearance ftw)?

The solution Sankalap Yaduraj Singh suggested, setting an additional margin constant to leadingMargin, does not work:

enter image description here
enter image description here

What I found out: if I set the layoutMargin via UIAppearance to anything greater than device default (usually 16 on iPad, 8 on iPhone), the larger margin is correctly applied:

// Experimental: TableViewCells Margin Bugfix for iOS 8.0 to 8.2
UITableViewCell.appearance().layoutMargins = UIEdgeInsetsMake(8, 17, 8, 16)

Notice the 17, instead of the 16 for this test on iPad.

As said it is a known iOS 8.1/8.2 bug. I already know that, the question is how to workaround in a clean way.

Fun fact: If I adjust UILabel's leading constraint constant in Reveal from 0 to 1 and back to 0, the position is correct. Looks like this 8.1/8.2 bug is an AutoLayout bug.


Answering my own question: As always the devil is in the detail.

The usual .ReloadData() in viewWillAppear is enough to fix AutoLayout for UITableView with iOS 8 (especially 8.1/8.2), except - and that's the reason for all the AutoLayout bugs in my question:

When your are using a UITableView inside a UISplitViewController and changing UISplitViewController`s preferredPrimaryColumnWidthFractionto something else larger than default (iirc 0.4).

Even when changing the primary column width just once, in a viewDidLoad() with added splitViewController?.setNeedsLayout() and splitViewController?.layoutIfNeeded() the above misalignments will occur under iOS 8 if you use dynamic sized UITableViewCells with UILabels which show long texts.

Cheers, thank you  for that long debugging session ;)

P.S. As a side note, I was able to observe a difference setting preservesSuperviewLayoutMargins in IB compared to code, too. If you a struggling with turning them on, do it in IB. Setting them in awakeFromNib() for the UITableViewCells and it's contentView behaves differently, at least for iOS 8 which we need to support for a while..