68

I noticed that in iOS 7, UITableViewCells have a line break in the separator of the cell that iOS 6 does not have. Is there a way to get rid of this line break? Changing the separator to none and then making UIViews with the color of the separator still causes the white separator to occur regardless.

Anthony Glyadchenko
  • 3,572
  • 7
  • 48
  • 66

17 Answers17

116

For iOS7:

if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
    [self.tableView setSeparatorInset:UIEdgeInsetsZero];
}

For iOS8:

First configure your table view as follows:

if ([self.tableView respondsToSelector:@selector(layoutMargins)]) {
    self.tableView.layoutMargins = UIEdgeInsetsZero;
}

Then in your cellForRowAtIndexPath: method, configure the cell as follows:

if ([cell respondsToSelector:@selector(layoutMargins)]) {
    cell.layoutMargins = UIEdgeInsetsZero;
}

Note: Include both layoutMargins and separatorInset, to support both iOS versions

Luis E. Prado
  • 2,131
  • 2
  • 16
  • 12
44

You can also set the 'Separator Inset' from the storyboard:

enter image description here

enter image description here

Tarek Hallak
  • 18,422
  • 7
  • 59
  • 68
  • 1
    For those who have a UITableView inside a UIView or UIViewController parent, you won't see the image above, but you will see the "Separator Insets" set to "Default" if you inspect the UITableView inside your .xib. Select "Custom" and change the left or right to 0. In other words, don't waste your time trying all this other stuff! Set the insets via IB.. – whyoz Oct 16 '13 at 01:06
  • 2
    This sounds right but didn't work for me. I created a new project, dragged in a TVC, made it the root VC, and changed left inset to 0. I ran the simulator, and the separators were still inset. Any idea why? nobre's solution (below) does work for me. – mkc842 Nov 13 '13 at 20:35
  • Thanks! You saved me so much time. – Ryan Walton Mar 01 '15 at 02:30
37

If you want to support older versions of iOS, you should check for the availability of this method before calling it:

if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
    [self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
boro
  • 852
  • 1
  • 10
  • 14
16

Figured it out.

[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
Anthony Glyadchenko
  • 3,572
  • 7
  • 48
  • 66
  • 1
    This worked for me as well. I don't understand, by the way, why separator got those breaks. And in my app in one table view same separator line are double and others are single. Why - no idea. – Valeriy Van Sep 10 '13 at 12:34
  • it did work for me for blank table view. but my custom reusable cell separators remained as the deafault – Karan Alangat Mar 03 '15 at 12:01
9

The selected answer did not work for me. But this yes and it works from ios 2.0:

   [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
anasaitali
  • 1,504
  • 21
  • 30
9

Swift version

iOS introduces the layoutMargins property on cells AND table views.

This property isn't available in iOS 7.0 so you need to make sure you check before assigning it!

However, Apple has added a **property to your cell that will prevent it from inheriting your Table View's margin settings. This way, your cells can configure their own margins independently of the table view. Think of it as an override.

This property is called preservesSuperviewLayoutMargins, and setting it to NO can allow you to override your Table View's layoutMargin settings with your own cell's layoutMargin setting. It both saves time (you don't have to modify the Table View's settings), and is more concise. Please refer to Mike Abdullah's answer for a detailed explanation.

NOTE: this is the proper, less messy implementation, as expressed in Mike Abdullah's answer; setting your cell's preservesSuperviewLayoutMargins=NO will ensure that your Table View does not override the cell settings.

First step - Setup your cell margins:

/*
    Tells the delegate the table view is about to draw a cell for a particular row.
*/
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
    forRowAtIndexPath indexPath: NSIndexPath)
{
    // Remove seperator inset
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
        cell.preservesSuperviewLayoutMargins = false
    }

    // Explictly set your cell's layout margins
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }
}

Setting the preservesSuperviewLayoutMargins property on your cell to NO should prevent your table view from overriding your cell margins. In some cases, it seems to not function properly.

Second step - Only if all fails, you may brute-force your Table View margins:

/*
    Called to notify the view controller that its view has just laid out its subviews.
*/
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Force your tableview margins (this may be a bad idea)
    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }

    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }
}

...and there you go! This should work on iOS 8 as well as iOS 7.

Note: tested using iOS 8.1 and 7.1, in my case I only needed to use The First Step of this explanation.

The Second Step is only required if you have unpopulated cell beneath the rendered cells, ie. if the table is larger than the number of rows in the table model. Not doing the second step would result in different separator offsets.

King-Wizard
  • 15,628
  • 6
  • 82
  • 76
8

For a permanent solution app-wide, call this in application:didFinishLaunching .. any tableview will be "fixed"

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
  [[UITableView appearance]setSeparatorInset:UIEdgeInsetsZero];
}
Rafael Nobre
  • 5,062
  • 40
  • 40
7

And in iOS 8, based on the Seth McFarlane post here, you need to start dealing with layoutMargins. The following did it for me:

  1. In ApplicationDidFinishLaunching, run the following:

    if ([UITableViewCell instancesRespondToSelector:@selector(setLayoutMargins:)]) {
        [[UITableViewCell appearance]setLayoutMargins:UIEdgeInsetsZero];
    }
    
  2. Create the following category on UITableView:

    @interface UITableView(WJAdditions)
    -(void) wjZeroSeparatorInset;
    @end
    
    @implementation UITableView (WJAdditions)
    -(void) wjZeroSeparatorInset {
    #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
      if ([self respondsToSelector:@selector(setLayoutMargins:)]) {
        self.layoutMargins = UIEdgeInsetsZero;
      }
    #endif
    #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
       if ([self respondsToSelector: @selector(setSeparatorInset:)])
          self.separatorInset = UIEdgeInsetsZero;
       }
    #endif
    }
    @end
    
  3. In your UITableViews, shortly after initializing, call

    [self wjZeroSeparatorInset];
    
  4. In your UITableViewControllers, you need the following:

    -(void) viewWillLayoutSubviews {
      [super viewWillLayoutSubviews];
      UITableView* tv = self.tableView;
      if ([tv respondsToSelector:@selector(setLayoutMargins:)]) {
        [tv setLayoutMargins:UIEdgeInsetsZero];
      }
    }
    
William Jockusch
  • 26,513
  • 49
  • 182
  • 323
6

In iOS 8, there appears to be a small bug. The custom value for separator inset doesn't get applied to the cells with text in it. I tried setting it from the interface builder and through code but neither worked. I've filed a bug report as well.

enter image description here

In the meantime, I have a small workaround to achieve this. I simply draw the line on the cell. Create a subclass of UITableViewCell and override the drawRect method. Also don't forget to set the separator property of the UITableView to None. Here is the code. It's in Swift but since its basically C, you can use the same thing in Objective-C as well.

override func drawRect(rect: CGRect) {
    super.drawRect(rect)

    let context = UIGraphicsGetCurrentContext()
    CGContextSetStrokeColorWithColor(context, UITableView().separatorColor.CGColor) // seperator color
    CGContextSetLineWidth(context, 2) // separator width

    CGContextMoveToPoint(context, 0, self.bounds.size.height)
    CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height)
    CGContextStrokePath(context)
}
Isuru
  • 30,617
  • 60
  • 187
  • 303
  • Thank you. `CGContextSetLineWidth(context, 1)` is closer to default, in case anyone wants a more "vanilla" look – Michael Jul 13 '15 at 15:48
4

Reset separatorInset fixes this problem for me:

if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
    [self.tableView setSeparatorInset:self.tableView.separatorInset];
}
3

The solution:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [tableView setLayoutMargins:UIEdgeInsetsZero];
    }

   if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}
Tea
  • 306
  • 4
  • 8
2

Beware as setting the separatorInset of tableView to UIEdgeInsetsZero seems to break the left margin of section titles at the same time! (at least it does on iOS 7.1)

If you want to display section titles with tableView:titleForHeaderInSection: and still get the desire effect of no line break between UITableViewCells, you must set the separatorInset directly on the cells instead of the tableView!

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // ...
    [cell setSeparatorInset:UIEdgeInsetsZero];
Bluezen
  • 850
  • 9
  • 13
1

For iOS8+ this worked for me,

tableView.layoutMargins = UIEdgeInsetsZero

and in cellForRowAtIndexPath method:

cell.layoutMargins = UIEdgeInsetsZero;
Mohammad Zaid Pathan
  • 16,304
  • 7
  • 99
  • 130
0
- (void)viewDidLoad
{
    [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];

    [super viewDidLoad];

    // Additional setup
}

Note: the setSeparatorStyle line has to be above the super call.

Matt Rundle
  • 1,609
  • 1
  • 9
  • 11
0
@implementation UITableView (HGApperance) 
-(void)setSeparatorXMargin:(CGFloat)margin{
    // iOS 7
    if ([self respondsToSelector:@selector(setSeparatorInset:)]) {
        [self setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self respondsToSelector:@selector(layoutMargins)]) {
        self.layoutMargins = UIEdgeInsetsZero;
    }
}
@end

For TableviewCell, Willam's answer works perfect.

Community
  • 1
  • 1
HamGuy
  • 916
  • 1
  • 7
  • 18
0

To iOS8 and above

If you find that all the solutions don't work like me, I think you may have used the subclass of UITableViewCell and override the layoutSubviews method, if you meet two the conditions, go on reading.

Do or check it step by step.

1、After alloc and init the UITableView, set its layoutMargins property.

if ([_tableView respondsToSelector:@selector(setLayoutMargins:)]) {
    _tableView.layoutMargins = UIEdgeInsetsZero ;
}

2、In the method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, after alloc and init your custom UITableViewCell, set its layoutMargins property.

if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
    cell.layoutMargins = UIEdgeInsetsZero ;
}

3、The most important part comes in. If you override the - (void)layoutSubviews method of UITableViewCell, don't forget to call its super.

- (void)layoutSubviews
{
    [super layoutSubviews] ;

    // layout the subviews
}
KudoCC
  • 6,912
  • 1
  • 24
  • 53
0

Xamarin.iOS Version

I extended the UITableView separator the full width in Xamarin.iOS on iOS 8.4 with help from posts by Luis E. Prado and King-Wizard. I had to set both SeparatorInset and LayoutMargins to get it working. I did not write checks for lower iOS versions since I am targeting iOS 8 and above.

I wrote the following two C# extension methods to set the UITableView separator full width at the UITableView or UITableViewCell level. You might use one or both of these methods depending on the desired effect (see the explanations below).

UITableView

Set the UITableView properties to alter the separators that appear after empty cells. This SetLayoutMarginsZero method could be called from the related ViewController's ViewDidLoad method.

public static void SetLayoutMarginsZero(this UITableView tableView)
{
    tableView.SeparatorInset = UIEdgeInsets.Zero;
    tableView.LayoutMargins = UIEdgeInsets.Zero;
}

UITableViewCell

Set the UITableViewCell properties to alter the separators that appear after populated cells. This SetLayoutMarginsZero method could be called from the TableViewSource GetCell method.

public static void SetLayoutMarginsZero(this UITableViewCell tableViewCell)
{
    tableViewCell.SeparatorInset = UIEdgeInsets.Zero;
    tableViewCell.LayoutMargins = UIEdgeInsets.Zero;
    tableViewCell.PreservesSuperviewLayoutMargins = false;
}
Mobile Dan
  • 6,444
  • 1
  • 44
  • 44