In iOS 14, Apple has FINALLY made this less painful.
If you want to...
- ...be able to select rows (for example in edit mode)
- ...prevent the default gray or blue cell highlight color
- ...keep the default system separator views
...this will help you. In your UITableViewCell
subclass, put this into the initializer:
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// Prevent cell highlighting while preserving selectability and separator views
if #available(iOS 14.0, *) {
var backgroundConfig = UIBackgroundConfiguration.listPlainCell()
backgroundConfig.backgroundColor = .clear
backgroundConfiguration = backgroundConfig
} else {
selectedBackgroundView = {
let bgView = UIView(frame: .zero)
bgView.translatesAutoresizingMaskIntoConstraints = false
bgView.backgroundColor = .clear
return bgView
}()
}
}
If you're only targeting iOS 14+ you can leave out the else
block and you're done. If you are also targeting iOS 13 and below, you'll also need to override layoutSubviews
to keep the separator view from disappearing (thanks to this comment: https://mcmap.net/q/333155/-uitableview-separator-line-disappears-when-selecting-cells-in-ios7). This will do the trick (also in your UITableViewCell
subclass):
override func layoutSubviews() {
super.layoutSubviews()
if #available(iOS 14.0, *) {
// no op
} else {
// Setting a custom selectedBackgroundView causes the system to hide the
// separatorView. If we want to have the separator, we need to show it again.
subviews.forEach { view in
if type(of: view).description() == "_UITableViewCellSeparatorView" {
view.alpha = 1.0
}
}
}
}
Enjoy.