Table View Separator Inset

The table view separator is that thin line drawn by default between table view cells. You control how far it extends to the leading and trailing edges with the seperatorInset property. Since iOS 7 this has been an inset based on the table cell margins. In iOS 11 Apple changed that to inset from the cell edges by default. That makes it easier to extend to the full table width but if you have been using an inset you may want to check how it now looks on iOS 11.

Separator Inset

The separatorInset property of UITableView is not new. It has been around since iOS 7 as a way to set the default inset for the separator between table view cells. It is a UIEdgeInsets but only the left and right values make any difference.

The effect is most obvious on the iPad, especially when using readable content guides. The separator is inset from the table view cell contentView layout margins taking into account the readable width:

iPad default separator inset

The iPhone is a little different in that the separator reaches all the way to the trailing edge (extending into the safe area on an iPhone X):

iPhone X default separator inset

Note: UIKit takes care of flipping the left and right insets for Right-To-Left languages.

You could always change this default inset by setting new left and right values for the separatorInset either in code or in Interface Builder:

tableView.separatorInset = UIEdgeInsetsMake(0, 50, 0, 50)

The problem with this is that the inset was always based on the default cell inset which took into account the content margins. if you wanted the separator to extend to the full width of the table view you had to mess with the cell margins with mixed results especially on the iPad.

Inset From Cell Edges (iOS 11)

Starting with iOS 11 if you set a separator inset it is now an inset from the cell edges and not from the default cell inset. For example, I can have a separator that stretches the full width of the table view by setting zero insets:

tableView.separatorInset = .zero

iPad inset from edges

From Automatic Insets

What I find confusing is that Apple has changed the way separator insets work by default in iOS 11. In iOS 10 and earlier they base the inset on the cell layout margins taking into account the readable content guide if used. In iOS 11 the separator inset is, by default, from the cell edges.

You can change this behaviour with the separatorInsetReference property of UITableView. This property, new in iOS 11, is an enum with two choices:

  • .fromCellEdges: inset is from cell edges
  • .fromAutomaticInsets: inset is from “default” table view insets (same as iOS 10)

The confusing thing for me is that the default value is .fromCellEdges. So if you have changed the separator inset for iOS 10 or earlier and want to maintain the same appearance for iOS 11 you need to choose .fromAutomaticInsets:

tableView.separatorInset = UIEdgeInsetsMake(0, 50, 0, 50)
if #available(iOS 11, *) {
  // Maintain iOS 10 style inset
  tableView.separatorInsetReference = .fromAutomaticInsets
}

Likewise if I want to use a full width separator on iOS 11 but keep the default for iOS 10:

if #available(iOS 11, *) {
  tableView.separatorInset = .zero
}

Customizing With Interface Builder

If you are doing your layout with Interface Builder the settings to customize the separator inset are available when viewing the table view in the attributes inspector. Change the value of Separator inset from Automatic to Custom to get the extra controls.

Separator inset

You can then set the left and right insets and switch between From Cell Edges or From Automatic Insets:

Custom separator inset

What Do I Need To Do?

This is pretty confusing to me. Here is a summary of what I think you need to know and where you may want to take action:

  • If you have never changed the separatorInset of your table views you don’t need to do anything.

  • If you have changed the separatorInset for earlier releases you should check how it looks with iOS 11. To maintain the same appearance you may want to change separatorInsetReference to .fromAutomaticInsets for iOS 11:

    if #available(iOS 11, *) {
      tableView.separatorInsetReference = .fromAutomaticInsets
    }
    
  • To inset from cell edges with iOS 11 set seperatorInset. Use #available if you want to keep the default inset for earlier releases. For example, a full width separator:

    if #available(iOS 11, *) {
      tableView.separatorInset = .zero
    }
    

    (The default for separatorInsetReference is .fromCellEdges.)

Further Reading