cornerRadius with border: Glitch around border cornerRadius with border: Glitch around border objective-c objective-c

cornerRadius with border: Glitch around border


I tried many solution and end by using UIBezierPath.

I create category of UIView and add method to make round rect and border.

This is method of that category:

- (void)giveBorderWithCornerRadious:(CGFloat)radius borderColor:(UIColor *)borderColor andBorderWidth:(CGFloat)borderWidth{    CGRect rect = self.bounds;        //Make round        // Create the path for to make circle        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rect                                                       byRoundingCorners:UIRectCornerAllCorners                                                             cornerRadii:CGSizeMake(radius, radius)];        // Create the shape layer and set its path        CAShapeLayer *maskLayer = [CAShapeLayer layer];        maskLayer.frame = rect;        maskLayer.path  = maskPath.CGPath;                // Set the newly created shape layer as the mask for the view's layer        self.layer.mask = maskLayer;        //Give Border        //Create path for border        UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rect                                                         byRoundingCorners:UIRectCornerAllCorners                                                               cornerRadii:CGSizeMake(radius, radius)];        // Create the shape layer and set its path        CAShapeLayer *borderLayer = [CAShapeLayer layer];                borderLayer.frame       = rect;        borderLayer.path        = borderPath.CGPath;        borderLayer.strokeColor = [UIColor whiteColor].CGColor;        borderLayer.fillColor   = [UIColor clearColor].CGColor;        borderLayer.lineWidth   = borderWidth;                //Add this layer to give border.        [[self layer] addSublayer:borderLayer];}

I get idea of using UIBezierPath from this amazing article: Thinking like a Bézier path

I get most of code from this two link:

Note: This is category method so self represent view on which this method is called. Like UIButton, UIImageView etc.


Here is a Swift 5 version of @CRDave's answer as an extension of UIView:

protocol CornerRadius {    func makeBorderWithCornerRadius(radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat)}extension UIView: CornerRadius {    func makeBorderWithCornerRadius(radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {        let rect = self.bounds        let maskPath = UIBezierPath(roundedRect: rect,                                    byRoundingCorners: .allCorners,                                    cornerRadii: CGSize(width: radius, height: radius))        // Create the shape layer and set its path        let maskLayer = CAShapeLayer()        maskLayer.frame = rect        maskLayer.path  = maskPath.cgPath        // Set the newly created shape layer as the mask for the view's layer        self.layer.mask = maskLayer        // Create path for border        let borderPath = UIBezierPath(roundedRect: rect,                                      byRoundingCorners: .allCorners,                                      cornerRadii: CGSize(width: radius, height: radius))        // Create the shape layer and set its path        let borderLayer = CAShapeLayer()        borderLayer.frame       = rect        borderLayer.path        = borderPath.cgPath        borderLayer.strokeColor = borderColor.cgColor        borderLayer.fillColor   = UIColor.clear.cgColor        borderLayer.lineWidth   = borderWidth * UIScreen.main.scale        //Add this layer to give border.        self.layer.addSublayer(borderLayer)    }}


This is Kamil Nomtek.com's answer updated to Swift 3+ and with some refinements (mostly semantics/naming and using a class protocol).

protocol RoundedBorderProtocol: class {    func makeBorder(with radius: CGFloat, borderWidth: CGFloat, borderColor: UIColor)}extension UIView: RoundedBorderProtocol {    func makeBorder(with radius: CGFloat, borderWidth: CGFloat, borderColor: UIColor) {        let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius))        // Create the shape layer and set its path        let maskLayer = CAShapeLayer()        maskLayer.frame = bounds        maskLayer.path = maskPath.cgPath        // Set the newly created shape layer as the mask for the view's layer        layer.mask = maskLayer        //Create path for border        let borderPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius))        // Create the shape layer and set its path        let borderLayer = CAShapeLayer()        borderLayer.frame = bounds        borderLayer.path = borderPath.cgPath        borderLayer.strokeColor = borderColor.cgColor        borderLayer.fillColor = UIColor.clear.cgColor        //The border is in the center of the path, so only the inside is visible.        //Since only half of the line is visible, we need to multiply our width by 2.        borderLayer.lineWidth = borderWidth * 2        //Add this layer to display the border        layer.addSublayer(borderLayer)    }}