I have some strange issue with UITableView
only in iOS 7.
UITableViewCellSeparator
disappears above the first row and below the last row. S
to expand on airpaulg answer, because it didn't entirely work for me..
i had to also implement the heightforfooter method to get the height
then i noticed the lightgraycolor is too dark. i fixed this by grabbing the current separator color of the tableview and using that:
UIColor *separatorGray = [self.briefcaseTableView separatorColor];
[footerSeparator setBackgroundColor:separatorGray];
@samvermette
I fixed the problem by using this delegate methods. Now it doesn't flicker:
-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
// fix for separators bug in iOS 7
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
}
-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath {
// fix for separators bug in iOS 7
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
}
I've found that the easiest solution is to, after reloading a cell, also reload the cell above:
if (indexPath.row > 0) {
NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section];
[self.tableView reloadRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationNone];
}
Complement to the answer of airpaulg.
So basically one has to implement two UITableDelegate methods. Here's my solution which works on both iOS7 and iOS6.
#define IS_OS_VERSION_7 (NSFoundationVersionNumber_iOS_6_1 < floor(NSFoundationVersionNumber))
#define UIColorFromRGB(hexRGBValue) [UIColor colorWithRed:((float)((hexRGBValue & 0xFF0000) >> 16))/255.0 green:((float)((hexRGBValue & 0xFF00) >> 8))/255.0 blue:((float)(hexRGBValue & 0xFF))/255.0 alpha:1.0]
// This will hide the empty table grid below the cells if they do not cover the entire screen
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIView *view = nil;
if (IS_OS_VERSION_7 /* && <is this the last section of the data source> */)
{
CGFloat height = 1 / [UIScreen mainScreen].scale;
view = [[UIView alloc] initWithFrame:CGRectMake(0., 0., 320., height)];
view.backgroundColor = UIColorFromRGB(0xC8C7CC);
view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
}
else
{
view = [UIView new];
}
return view;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if (IS_OS_VERSION_7 /* && <is this the last section of the data source> */)
{
return 1 / [UIScreen mainScreen].scale;
}
else
{
// This will hide the empty table grid below the cells if they do not cover the entire screen
return 0.01f;
}
}
Here is a simple, clean and non-intrusive workaround. It involves calling a category method that will fix the separators.
All you need to do is to walk down the hierarchy of the cell and un-hide the separator. Like this:
for (UIView *subview in cell.contentView.superview.subviews) {
if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
subview.hidden = NO;
}
}
What I recommend is to add this to a category on UITableViewCell, like this:
@interface UITableViewCell (fixSeparator)
- (void)fixSeparator;
@end
@implementation UITableViewCell (fixSeparator)
- (void)fixSeparator {
for (UIView *subview in self.contentView.superview.subviews) {
if ([NSStringFromClass(subview.class) hasSuffix:@"SeparatorView"]) {
subview.hidden = NO;
}
}
}
@end
Because the separator can disappear in different cell than the one currently selected, it's probably a good idea to call this fix on all cells in the table view. For that, you can add a category to UITableView that goes like this:
@implementation UITableView (fixSeparators)
- (void)fixSeparators {
for (UITableViewCell *cell in self.visibleCells) {
[cell fixSeparator];
}
}
@end
With this in place, you can call -fixSeparatos
on your tableView right after the action that causes them to disappear. In my case, it was after calling [tableView beginUpdates]
and [tableView endUpdates]
.
As I stated at the beginning, I've tested this on both iOS 8 and iOS 9. I presume it will work even on iOS 7 but I don't have a way to try it there. As you are probably aware, this does fiddle with internals of the cell so it could stop working in some future release. And Apple could theoretically (0.001% chance) reject your app because of this, but I can't see how they could even find out what you are doing there (checking the suffix of a class can't be detected by static analyzers as something bad, IMO).
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.