11

I have several custom UITableViewCells in my app, mostly defined by nibs. When moving to iOS 8 and Xcode 6 the margins on the left and right are incorrect. These cells are often interspersed in a table view with default cells.

I made a sample project, here is the margin issue I'm talking about: margin issue

The only thing I've been able to find that relates to this is the new property layoutMargins. For UITableViewCells its value seems to change depending on the device the app is running on:

iPhone 6 and below - layoutMargin: {8, 16, 8, 16}
iPhone 6 Plus - layoutMargin: {8, 20, 8, 20}

This seems to line up with the margins I'm seeing on the standard cells. However, the content for my custom cells is inside the cells contentView, which has the standard UIView layoutMargin of {8, 8, 8, 8}. This means any auto layout constraints that are bound to the Container Margin are adding the incorrect spacing.

The only way I've found to fix this is by adding the following in cellForRowAtIndexPath:

cell.contentView.layoutMargins = cell.layoutMargins;

This doesn't seem like a very good solution going forward (especially since I'd need to wrap it in checks for iOS8 to maintain compatibility).

Does anyone have any ideas? I feel like I must be missing something.

pkamb
  • 33,281
  • 23
  • 160
  • 191
simon
  • 2,635
  • 4
  • 20
  • 21

4 Answers4

15

You might want to check out the preservesSuperviewLayoutMargins property. It sound like what you are looking for.

Add the following to any cells that need to be consistently spaced with the standard cells:

- (void)layoutSubviews {
    [super layoutSubviews];

    if ([self.contentView respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        self.contentView.preservesSuperviewLayoutMargins = YES;
    }
}
simon
  • 2,635
  • 4
  • 20
  • 21
Walt Sellers
  • 3,806
  • 30
  • 35
5

In your UITableViewCell subclass, override layoutMarginsDidChange and set the contentView's layoutMargins to match the cell's layoutMargins:

- (void)layoutMarginsDidChange {
    contentView.layoutMargins = layoutMargins
}

i found this to be more reliable than setting preservesSuperviewLayoutMargins to YES.

damacster
  • 226
  • 2
  • 7
0

preservesSuperviewLayoutMargins solves it for iOS8. The code below includes that, and additional code which solves it for ios7.1.

class CustomTableViewCell: UITableViewCell {

    @IBOutlet weak var mainLabel: UILabel!

    override func layoutSubviews() {
        super.layoutSubviews()

        if contentView.respondsToSelector(Selector("preservesSuperviewLayoutMargins")) {
            contentView.preservesSuperviewLayoutMargins = true
        } else {
            if mainLabel != nil {
                let leftConstraint = NSLayoutConstraint(item: mainLabel,
                    attribute: .Leading,
                    relatedBy: .Equal,
                    toItem: contentView,
                    attribute: .Leading,
                    multiplier: 1.0,
                    constant: 16.0);
                addConstraint(leftConstraint);
            }
        }
    }

}
Elijah
  • 8,381
  • 2
  • 55
  • 49
0

To remove that funky left margin in iOS 8+, in your table view:

table.separatorInset = UIEdgeInsets.zero     // or UIEdgeInsetsZero

You may also need:

table.layoutMargins = UIEdgeInsets.zero

Credit to https://stackoverflow.com/a/30640595/385273.

Ben
  • 54,723
  • 49
  • 178
  • 224