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:
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):
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
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.
You can then set the left and right insets and switch between From Cell Edges
or From Automatic Insets
:
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 changeseparatorInsetReference
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
.)