22

How we can have the border around each section of tableview? Attached is the image to show what I am looking for. If you look at the image, it has a border around each tableview section.

enter image description here

itsaboutcode
  • 24,525
  • 45
  • 110
  • 156

8 Answers8

26

For this issue I made an adaptation of jvanmetre answer for rounding tableviews corners, just add the tableView:willDisplayCell:forRowAtIndexPath: delegate method with the following code (a simple copy/paste should work), it should work for grouped tables too. I commented where you should set the width and color of the border.

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

    if ([cell respondsToSelector:@selector(tintColor)]) {
        CGFloat cornerRadius = 5.f;
        cell.backgroundColor = UIColor.clearColor;
        CAShapeLayer *layer = [[CAShapeLayer alloc] init];
        CGMutablePathRef pathRef = CGPathCreateMutable();
        CGRect bounds = CGRectInset(cell.bounds, 10, 0);
        BOOL addLine = NO;
        if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
            CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
        } else if (indexPath.row == 0) {
            CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetMidX(bounds), CGRectGetMinY(bounds), cornerRadius);
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
            addLine = YES;
        } else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
            CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds), CGRectGetMidX(bounds), CGRectGetMaxY(bounds), cornerRadius);
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
        } else {
            CGPathAddRect(pathRef, nil, bounds);
            addLine = YES;
        }
        layer.path = pathRef;
        CFRelease(pathRef);
        //set the border color
        layer.strokeColor = [UIColor lightGrayColor].CGColor;
        //set the border width
        layer.lineWidth = 1;
        layer.fillColor = [UIColor colorWithWhite:1.f alpha:1.0f].CGColor;


        if (addLine == YES) {
            CALayer *lineLayer = [[CALayer alloc] init];
            CGFloat lineHeight = (1.f / [UIScreen mainScreen].scale);
            lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight);
            lineLayer.backgroundColor = tableView.separatorColor.CGColor;
            [layer addSublayer:lineLayer];
        }

        UIView *testView = [[UIView alloc] initWithFrame:bounds];
        [testView.layer insertSublayer:layer atIndex:0];
        testView.backgroundColor = UIColor.clearColor;
        cell.backgroundView = testView;
    }
}

Also, remember to set the separator property of the table to none in the Interface Builder, (it's by default to single line), if you are creating the table programmatically you should set the property like this

yourTableView.separatorStyle = UITableViewCellSeparatorStyleNone
Community
  • 1
  • 1
Boris
  • 11,373
  • 2
  • 33
  • 35
18

Here is Asad's answer updated to swift 3

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if (cell.responds(to: #selector(getter: UIView.tintColor))) {
        let cornerRadius: CGFloat = 5
        cell.backgroundColor = UIColor.clear
        let layer: CAShapeLayer  = CAShapeLayer()
        let pathRef: CGMutablePath  = CGMutablePath()
        let bounds: CGRect  = cell.bounds.insetBy(dx: 10, dy: 0)
        var addLine: Bool  = false
        if (indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section)-1) {
            pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
        } else if (indexPath.row == 0) {
            pathRef.move(to: CGPoint(x:bounds.minX,y:bounds.maxY))
            pathRef.addArc(tangent1End: CGPoint(x:bounds.minX,y:bounds.minY), tangent2End: CGPoint(x:bounds.midX,y:bounds.minY), radius: cornerRadius)

            pathRef.addArc(tangent1End: CGPoint(x:bounds.maxX,y:bounds.minY), tangent2End: CGPoint(x:bounds.maxX,y:bounds.midY), radius: cornerRadius)
            pathRef.addLine(to: CGPoint(x:bounds.maxX,y:bounds.maxY))
            addLine = true;
        } else if (indexPath.row == tableView.numberOfRows(inSection: indexPath.section)-1) {

            pathRef.move(to: CGPoint(x:bounds.minX,y:bounds.minY))
            pathRef.addArc(tangent1End: CGPoint(x:bounds.minX,y:bounds.maxY), tangent2End: CGPoint(x:bounds.midX,y:bounds.maxY), radius: cornerRadius)

            pathRef.addArc(tangent1End: CGPoint(x:bounds.maxX,y:bounds.maxY), tangent2End: CGPoint(x:bounds.maxX,y:bounds.midY), radius: cornerRadius)
            pathRef.addLine(to: CGPoint(x:bounds.maxX,y:bounds.minY))

        } else {
            pathRef.addRect(bounds)
            addLine = true
        }
        layer.path = pathRef
        //CFRelease(pathRef)
        //set the border color
        layer.strokeColor = UIColor.lightGray.cgColor;
        //set the border width
        layer.lineWidth = 1
        layer.fillColor = UIColor(white: 1, alpha: 1.0).cgColor


        if (addLine == true) {
            let lineLayer: CALayer = CALayer()
            let lineHeight: CGFloat  = (1 / UIScreen.main.scale)
            lineLayer.frame = CGRect(x:bounds.minX, y:bounds.size.height-lineHeight, width:bounds.size.width, height:lineHeight)
            lineLayer.backgroundColor = tableView.separatorColor!.cgColor
            layer.addSublayer(lineLayer)
        }

        let testView: UIView = UIView(frame:bounds)
        testView.layer.insertSublayer(layer, at: 0)
        testView.backgroundColor = UIColor.clear
        cell.backgroundView = testView
    }

}
gomezluisj
  • 433
  • 5
  • 14
2

Here is the swift version of accepted answer.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (cell.respondsToSelector("tintColor")) {
        var cornerRadius: CGFloat = 5;
        cell.backgroundColor = UIColor.clearColor()
        var layer: CAShapeLayer  = CAShapeLayer()
        var pathRef: CGMutablePathRef  = CGPathCreateMutable()
        var bounds: CGRect  = CGRectInset(cell.bounds, 10, 0)
        var addLine: Bool  = false
        if (indexPath.row == 0 && indexPath.row == tableView.numberOfRowsInSection(indexPath.section)-1) {
            CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
        } else if (indexPath.row == 0) {
            CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetMidX(bounds), CGRectGetMinY(bounds), cornerRadius);
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
            addLine = true;
        } else if (indexPath.row == tableView.numberOfRowsInSection(indexPath.section)-1) {
            CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds), CGRectGetMidX(bounds), CGRectGetMaxY(bounds), cornerRadius);
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
        } else {
            CGPathAddRect(pathRef, nil, bounds);
            addLine = true;
        }
        layer.path = pathRef;
        //CFRelease(pathRef);
        //set the border color
        layer.strokeColor = UIColor.lightGrayColor().CGColor;
        //set the border width
        layer.lineWidth = 1;
        layer.fillColor = UIColor(white: 1, alpha: 1.0).CGColor;


        if (addLine == true) {
            var lineLayer: CALayer = CALayer();
            var lineHeight: CGFloat  = (1 / UIScreen.mainScreen().scale);
            lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight);
            lineLayer.backgroundColor = tableView.separatorColor!.CGColor;
            layer.addSublayer(lineLayer);
        }

        var testView: UIView = UIView(frame:bounds)
        testView.layer.insertSublayer(layer, atIndex: 0)
        testView.backgroundColor = UIColor.clearColor()
        cell.backgroundView = testView
    }

}
Asad
  • 73
  • 8
2

Here is another approach I've ended up that may help someone. It draws the border for each section with a predefined color and width without altering other properties of the cells. It doesn't give you a rounded section (probably it can be modified accordingly) but it gives a good degree of control of the lines to draw. The approach also addresses device rotation.

typedef enum CellBorderMask{
    CellBorderMaskLeft      = 1 << 0,
    CellBorderMaskRigth     = 1 << 1,
    CellBorderMaskTop       = 1 << 2,
    CellBorderMaskBottom    = 1 << 3
}CellBorderMask;




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

    CellBorderMask mask;
    if (indexPath.row == 0){
        mask |= CellBorderMaskTop;
    }

    if(indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1) {
        mask |= CellBorderMaskBottom;
    }
    mask |= CellBorderMaskRigth | CellBorderMaskLeft;
    [self addBorder:mask forView:cell.contentView];
}

-(void)addBorder:(CellBorderMask)mask forView:(UIView *)view{
    float onePixel = (1.f / [UIScreen mainScreen].scale);
    float lineWidth = 1 * onePixel;
    CGColorRef cgBorderColor = [UIColor redColor].CGColor;


    CALayer *topBorder = [CALayer layer];
    CALayer *bottomBorder = [CALayer layer];
    CALayer *leftBorder = [CALayer layer];
    CALayer *rightBorder = [CALayer layer];

    //tag layers so it's possible to find and remove them later 
    topBorder.name = @"Border";
    bottomBorder.name = @"Border";
    leftBorder.name = @"Border";
    rightBorder.name = @"Border";

    //remove previously set border layers so they doesn't produce unwanted effect on orientation change
    [self cleanUpOldBorderLayers:view];

    topBorder.frame = CGRectMake(0.0f, 0.0f, view.bounds.size.width, lineWidth);
    topBorder.backgroundColor = cgBorderColor;

    bottomBorder.frame = CGRectMake(0.0f, view.bounds.size.height - lineWidth, view.bounds.size.width, lineWidth);
    bottomBorder.backgroundColor = cgBorderColor;

    leftBorder.frame = CGRectMake(0.0f, 0.0f, lineWidth, view.bounds.size.height);
    leftBorder.backgroundColor = cgBorderColor;

    rightBorder.frame = CGRectMake(view.bounds.size.width - lineWidth, 0.0f, lineWidth, view.bounds.size.height);
    rightBorder.backgroundColor = cgBorderColor;
    if(mask & CellBorderMaskTop){
        [view.layer addSublayer:topBorder];
    }
    if(mask & CellBorderMaskBottom){
        [view.layer addSublayer:bottomBorder];
    }
    if(mask & CellBorderMaskLeft){
        [view.layer addSublayer:leftBorder];
    }
    if(mask & CellBorderMaskRigth){
        [view.layer addSublayer:rightBorder];
    }
}

-(void)cleanUpOldBorderLayers:(UIView *)view{
    NSMutableArray *layerArray = [NSMutableArray new];
    for (CALayer *layer in view.layer.sublayers) {
        if([@"Border" isEqualToString:layer.name]){
            [layerArray addObject:layer];
        }
    }
    for (CALayer *layer in layerArray) {
        [layer removeFromSuperlayer];
    }
}


-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    //need to trigger tableView:willDisplayCell: method on orientation change. 
    //Suggest a better method for this if there is one
    [self.tableView reloadData];
}

I use tableView's reloadData method to redraw cells which I believe is not the best approach. Please advice on alternative method in comments and I'll updated the code.

To add border to header/footer just create a custom view in viewForHeaderInSection/viewForFooterInSection delegate methods and pass the view to the addBorder:forView method above before returning it from your delegate.

vir us
  • 9,920
  • 6
  • 57
  • 66
1

An working fix for different number of rows in different sections

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            let cornerRadius: CGFloat = 0.0
            cell.backgroundColor = UIColor.clear
            let layer: CAShapeLayer = CAShapeLayer()
            let pathRef: CGMutablePath = CGMutablePath()
            //dx leading an trailing margins
            let bounds: CGRect = cell.bounds.insetBy(dx: 8, dy: 0)
            var addLine: Bool = false

            if indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
                pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
            } else if indexPath.row == 0 {
                pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
                pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.minY),
                               tangent2End: CGPoint(x: bounds.midX, y: bounds.minY),
                               radius: cornerRadius)

                pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.minY),
                               tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY),
                               radius: cornerRadius)
                pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
                addLine = true
            } else if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
                pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
                pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY),
                               tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY),
                               radius: cornerRadius)

                pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY),
                               tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY),
                               radius: cornerRadius)
                pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
            } else {
                pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
                pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY),
                               tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY),
                               radius: cornerRadius)

                pathRef.move(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
                pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY),
                               tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY),
                               radius: cornerRadius)
                pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
                addLine = true
            }

            layer.path = pathRef
            layer.strokeColor = UIColor.lightGray.cgColor
            layer.lineWidth = 1.0
            layer.fillColor = UIColor.clear.cgColor

            if addLine == true {
                let lineLayer: CALayer = CALayer()
                let lineHeight: CGFloat = (1 / UIScreen.main.scale)
                lineLayer.frame = CGRect(x: bounds.minX, y: bounds.size.height - lineHeight, width: bounds.size.width, height: lineHeight)
                lineLayer.backgroundColor = UIColor.clear.cgColor
                layer.addSublayer(lineLayer)
            }

            let backgroundView: UIView = UIView(frame: bounds)
            backgroundView.layer.insertSublayer(layer, at: 0)
            backgroundView.backgroundColor = .clear
            cell.backgroundView = backgroundView

        }
0

Here is Swift3 version of the answer:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let cornerRadius: CGFloat = 0.0
    cell.backgroundColor = UIColor.clear
    let layer: CAShapeLayer = CAShapeLayer()
    let pathRef: CGMutablePath = CGMutablePath()
    let bounds: CGRect = cell.bounds.insetBy(dx: 10, dy: 0)
    var addLine: Bool = false

    if indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
        pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
    } else if indexPath.row == 0 {
        pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
        pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.minY), tangent2End: CGPoint(x: bounds.midX, y: bounds.minY), radius: cornerRadius)
        pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.minY), tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
        pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
        addLine = true
    } else if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
        pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
        pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY), tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY), radius: cornerRadius)
        pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY), tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
        pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
    } else {
        pathRef.addRect(bounds)
        addLine = true
    }

    layer.path = pathRef
    layer.strokeColor = UIColor.black.cgColor
    layer.lineWidth = 0.5
    layer.fillColor = UIColor(white: 1, alpha: 1.0).cgColor

    if addLine == true {
        let lineLayer: CALayer = CALayer()
        let lineHeight: CGFloat = (1 / UIScreen.main.scale)
        lineLayer.frame = CGRect(x: bounds.minX, y: bounds.size.height - lineHeight, width: bounds.size.width, height: lineHeight)
        lineLayer.backgroundColor = tableView.separatorColor!.cgColor
        layer.addSublayer(lineLayer)
    }

    let backgroundView: UIView = UIView(frame: bounds)
    backgroundView.layer.insertSublayer(layer, at: 0)
    backgroundView.backgroundColor = UIColor.clear
    cell.backgroundView = backgroundView
}
0

This answer fix issue that give radius has more than 2 cell in section.

radius: cornerRadius -> 0.0

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let cornerRadius: CGFloat = 4.0
        cell.backgroundColor = UIColor.clear
        let layer: CAShapeLayer = CAShapeLayer()
        let pathRef: CGMutablePath = CGMutablePath()
        //dx leading an trailing margins
        let bounds: CGRect = cell.bounds.insetBy(dx: 15, dy: 0)
        var addLine: Bool = false
        
        if indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
            pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
        } else if indexPath.row == 0 {
            pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
            pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.minY),
                           tangent2End: CGPoint(x: bounds.midX, y: bounds.minY),
                           radius: cornerRadius)
            
            pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.minY),
                           tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY),
                           radius: cornerRadius)
            pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
            addLine = true
        } else if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
            pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
            pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY),
                           tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY),
                           radius: cornerRadius)
            
            pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY),
                           tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY),
                           radius: cornerRadius)
            pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        } else {
            pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
            pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY),
                           tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY),
                           radius: 0.0)
            
            pathRef.move(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
            pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY),
                           tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY),
                           radius: 0.0)
            pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
            addLine = true
        }
        
        layer.path = pathRef
        layer.strokeColor = UIColor(fromHexString: "#D8D8D8")?.cgColor
        layer.lineWidth = 1.0
        layer.fillColor = UIColor.clear.cgColor
        
        if addLine == true {
            let lineLayer: CALayer = CALayer()
            let lineHeight: CGFloat = (1 / UIScreen.main.scale)
            lineLayer.frame = CGRect(x: bounds.minX, y: bounds.size.height - lineHeight, width: bounds.size.width, height: lineHeight)
            lineLayer.backgroundColor = UIColor.clear.cgColor
            layer.addSublayer(lineLayer)
        }
        
        let backgroundView: UIView = UIView(frame: bounds)
        backgroundView.layer.insertSublayer(layer, at: 0)
        backgroundView.backgroundColor = .clear
        cell.backgroundView = backgroundView
        
    }
Ali Ihsan URAL
  • 1,894
  • 1
  • 20
  • 43
-1

I modified above posted code, now this code create border for section. Tested in swift4.2

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let cornerRadius: CGFloat = 24
        cell.backgroundColor = .clear

        let layer = CAShapeLayer()
        let pathRef = CGMutablePath()
        let bounds = cell.bounds.insetBy(dx: 10, dy: 0)
        var addLine = false

        if indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
            pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
        } else if indexPath.row == 0 {
            pathRef.move(to: .init(x: bounds.minX, y: bounds.maxY))
            pathRef.addArc(tangent1End: .init(x: bounds.minX, y: bounds.minY), tangent2End: .init(x: bounds.midX, y: bounds.minY), radius: cornerRadius)
            pathRef.addArc(tangent1End: .init(x: bounds.maxX, y: bounds.minY), tangent2End: .init(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
            pathRef.addLine(to: .init(x: bounds.maxX, y: bounds.maxY))
            addLine = true
        } else if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
            pathRef.move(to: .init(x: bounds.minX, y: bounds.minY))
            pathRef.addArc(tangent1End: .init(x: bounds.minX, y: bounds.maxY), tangent2End: .init(x: bounds.midX, y: bounds.maxY), radius: cornerRadius)
            pathRef.addArc(tangent1End: .init(x: bounds.maxX, y: bounds.maxY), tangent2End: .init(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
            pathRef.addLine(to: .init(x: bounds.maxX, y: bounds.minY))
        } else {
           //pathRef.addRect(bounds)

            let pathInnerRef = CGMutablePath()
            pathInnerRef.move(to: .init(x: bounds.minX, y: bounds.minY))
            pathInnerRef.addLine(to: .init(x: bounds.minX, y: bounds.maxY))

            pathInnerRef.move(to: .init(x: bounds.maxX, y: bounds.minY))
            pathInnerRef.addLine(to: .init(x: bounds.maxX, y: bounds.maxY))
            pathRef.addPath(pathInnerRef)
            addLine = true
        }

        layer.path = pathRef
        layer.fillColor = UIColor.clear.cgColor
        layer.strokeColor = UIColor.black.cgColor


        if (addLine == true) {
            let lineLayer = CALayer()
            let lineHeight = 1.0 / UIScreen.main.scale
            lineLayer.frame = CGRect(x: bounds.minX + 10, y: bounds.size.height - lineHeight, width: bounds.size.width - 10, height: lineHeight)
            lineLayer.backgroundColor = UIColor.clear.cgColor//tableView.separatorColor?.cgColor
            lineLayer.addBorder(edge: .left, color: UIColor.black, thickness: 2.0)
            lineLayer.addBorder(edge: .right, color: UIColor.black, thickness: 2.0)
            layer.addSublayer(lineLayer)
        }


        let testView = UIView(frame: bounds)
        testView.layer.insertSublayer(layer, at: 0)
        testView.backgroundColor = .clear

        cell.backgroundView = testView   
}
Saeed Zhiany
  • 2,051
  • 9
  • 30
  • 41