UITableViewCell Separator disappearing in iOS7
Solution 1
I dumped the subview hierarchy of affected cells and found that the _UITableViewCellSeparatorView
was set to hidden. No wonder it's not shown!
I overrode layoutSubviews
in my UITableViewCell
subclass and now the separators are displayed reliably:
Objective-C:
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *subview in self.contentView.superview.subviews) {
if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
subview.hidden = NO;
}
}
}
Swift:
override func layoutSubviews() {
super.layoutSubviews()
guard let superview = contentView.superview else {
return
}
for subview in superview.subviews {
if String(subview.dynamicType).hasSuffix("SeparatorView") {
subview.hidden = false
}
}
}
The other solutions proposed here didn't work consistently for me or seem clunky (adding custom 1 px footer views).
Solution 2
This worked for me:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// fix for separators bug in iOS 7
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
Solution 3
I also had the problem with missing separator and I found out that the problem only occured when heightForRowAtIndexPath
was returning a decimal number. Solution:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return ceil(yourHeight) // Ceiling this value fixes disappearing separators
}
Solution 4
Did you try adding a UIView of height 1 in the header and the footer of the table with light gray background color? Basically it'll mock the first and last separators.
Solution 5
We encountered this issue in our app. When the user selected a cell, a new table view was pushed onto the navigation controller stack and then when the user popped it off, the separator was missing. We solved it by putting [self.tableView deselectRowAtIndexPath:indexPath animated:NO];
in the didSelectRowAtIndexPath
table view delegate method.
B.S.
Updated on September 27, 2020Comments
-
B.S. over 3 years
I have some strange issue with
UITableView
only in iOS 7.UITableViewCellSeparator
disappears above the first row and below the last row. Sometimes after selecting the rows or some scrolling actions it appears.In my case
tableView
is loaded from theStoryboard
withUITableViewStylePlain
style. The problem is surely not inUITableViewCellSeparatorStyle
, which is not changed from defaultUITableViewCellSeparatorStyleSingleLine
.As I read at Apple Dev Forums (here and here) other people have such problem and some workarounds are found, for example:
Workaround: disable the default selection and recreate the behaviour in a method trigged by a tapGestureRecognizer.
But I am still searching for the reason of such separator strange behaviour.
Any ideas?
Update: As I saw in XCode 5.1 DP and iOS 7.1 beta, Apple tried to fix this problem. Now separator is shown as needed sometimes below the last row, after some refreshing, but not after tableview creation.
-
B.S. over 10 yearsWhat about the case if I do not implement even heightForRowAtIndexPath method?
-
Joney Spark over 10 yearsInteresting. However, it happens in my project as well - and heightForRowAtIndexPath isn't implemented. In IB row/cell height is 100.
-
Joney Spark over 10 yearsThis workaround fixed it for me; however, I reversed it - to retain the selection. So, first deselect, then re-select.
-
Gergely Kovacs over 10 yearsIt did not solve the issue for me and I do have the heightForRowAtIndexPath method.
-
Nick Frolov over 10 yearsSolves the issue at least partially. The cell does seem to be confused about non-integer heights.
-
airpaulg over 10 yearsI don't know what to override when you say "after the data is reloaded"
-
wrightak over 10 yearsHave you tried
self.tableView.allowsMultipleSelection = NO;
? -
skinsfan00atg over 10 yearsthis sounds good, but how exactly do you do this? use viewforfooter?
-
skinsfan00atg over 10 yearsisn't as easy as it sounds, for some reason i had to also implement heightforfooter otherwise the height specified in the initwithframe was ignored. i also notice though that the lightgraycolor is not the same color so this won't really work. might have to make a custom gray
-
trss about 10 yearsYou need to ceil the number of pixels and then divide by screen scale factor to get points which is okay to be in decimal. If you don't do this, it won't be retina optimized.
-
NiñoScript about 10 yearsYou deserve more up votes, this is exactly what I needed, I added it in a category, so now after I do [tableView reloadData], if this bug happens (in my case the footer separator that was hidden is reappearing), I call [tableView reloadSeparators];
-
surfrider almost 10 yearsWorked for me. Thanks. Any other methods didn't help me (include separator style change from samvermette's answer).
-
agarcian almost 10 yearsThis fix the issue for me. Thank you so much!
-
Vitalii Boiarskyi almost 10 yearsI have used your method but not in subclass I had added a category to UITableViewCell. It helped me. Thanks.
-
Ortwin Gentz almost 10 yearsOf course it's also possible in a category. Since this requires method swizzling, I went for the simple subclass approach.
-
juhan_h almost 10 yearsThis is the only solution that worked for me. My problem popped up whe the UITableView had enough rows to be scrollable. That "hasSuffix:" part is quite fragile though.
-
JackyJohnson almost 10 yearsthat's pretty janky IMO
-
airpaulg almost 10 yearsYeah I fully agree. It's the sole workaround I found right after iOS 7's release, is there any better approach now?
-
Jeff over 9 yearsTo match the color, use tableView.separatorColor
-
Foriger about 9 yearsWorks for me. Maybe question is silly, but isn't this using of Private API ?
-
Ortwin Gentz about 9 yearsTechnically it's not using private API and your app won't be rejected because of this. It relies on an implementation detail though and could break in a future iOS version.
-
David about 9 years@Foriger if you worry of using hasSuffix:@"SeparatorView", try to replace it with if(CGRectGetHeight(subview.frame) < 1.1). It probably even would work faster whether you don't use any other 1px custom views in your cell. I chose 1.1px 'cos in Retina UITableViewSeparator has 0.5 points height, but for non-Retina it could be 1.0.
-
Alex Sfinx87 almost 9 yearsWorks for me, grouped UITableView (iOS 7 and iOS8).
-
ObjectiveTC almost 9 yearsYES. This worked for me, after converting over to latest version of Swift. ++ for calling fixSeparators after every call to tableView.endUpdates().
-
Lukas Petr almost 9 yearsI am glad this was helpful to you! I really believe this is the best solution, so hopefully more people will discover it.
-
Dan Dyer over 8 yearsAlthough this mostly fixed the problem for me, for some reason one of my separators was still disappearing. Combining this fix with the toggling of
tableView.separatorStyle
suggested in other answers (which by itself made no difference for me) made it work for all of the separators. -
Brett about 8 yearsSetting clipSubviews to false in the storyboard for both the cell and the contentView fixed the issue! Needs more up votes!
-
Rene Juuse about 7 yearsSetting clipsToBounds to YES on the cells was enough for me.