In my tableView I set a separator line between cells. I am allowing selection of multiple cells. Here\'s my code for setting selected cell background color:
This simple call did it for me on iOS 8.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// ....
[tableView deselectRowAtIndexPath:indexPath animated:YES]
// ....
}
You could also trying setting the separator insets to 0. I did that and it solved the problem, but the trade-off is you lose the nice look of the insets.
In iOS 14, Apple has FINALLY made this less painful.
If you want to...
...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://stackoverflow.com/a/47573308/171933). 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.
For those of you looking for a solution in Swift, this fixed the issue for me. In your cellForRowAtIndexPath
method, after you call dequeueReusableCellWithIdentifier
, you just need to set the cells selectionStyle
to .None
Here's the code:
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:TextTableViewCell = tableView!.dequeueReusableCellWithIdentifier("textCell", forIndexPath: indexPath) as! TextTableViewCell
cell.selectionStyle = .None // This fixes the disappearing border line issue
I resolved this issue (hackishly) by reloading not just the selected cell but by also reloading the one right above it. None of the other solutions above worked for me.
NSIndexPath *indexPathOfCellAbove = [NSIndexPath indexPathForRow:(indexPath.row - 1) inSection:indexPath.section];
if (indexPath.row > 0)
[self.tableView reloadRowsAtIndexPaths:@[indexPathOfCellAbove, indexPath] withRowAnimation:UITableViewRowAnimationNone];
else
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
What I did was this:
In my case, I didn't want my rows shaded at all when selected, so I left the selected background view clear, but you can make it whatever color you like.
Also, I am not using autolayout, so just set my sizes appropriately. I presume with autolayout you would have to set up appropriate constraints.
For me, this completely resolved the problem (though I agree that this really does seem to be a bug in ios 7).