1
votes

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() {
        super.awakeFromNib()
        // Initialization code
    }

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

        customTextLabel.text = text
        customTextLabel.accessibilityLabel = text
    }

    override func layoutSubviews() {
        super.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.

2

2 Answers

0
votes

You can set the left margin with the help of auto layout.

Look it the image below.

enter image description here

0
votes

Update 04/26/2016

While the below strikethrough text is valid to some extend, it's not as simple as that. AutoLayout in UITableViewCells is broken for iOS 8.1/8.2 and buggy for anything older than iOS 9. Period.

I created a small demo with two simple multi-line labels (over/under), both preserving superview margins. Under iOS 8.1/8.2 they don't preserve the superview margin with long text and the height is incorrect when rotated.

Here is the same problem, in a demo repo of an Apple UIKit developer Tyler Fox: https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8

And my Issue on that Repo: https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8/issues/39

Still seeking help..

Frederik

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..