281

I saw in the inspector that I can change the background color, but I'd like to also change the border color and thickness, is this possible?

Frostmourne
  • 156
  • 1
  • 19
Shai UI
  • 50,568
  • 73
  • 204
  • 309

14 Answers14

601

You need to use view's layer to set border property. e.g:

#import <QuartzCore/QuartzCore.h>
...
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 3.0f;

You also need to link with QuartzCore.framework to access this functionality.

Vladimir
  • 170,431
  • 36
  • 387
  • 313
  • Is there any way to set different width/colors for every side? – llullulluis Oct 10 '11 at 16:13
  • 2
    @lluismontero I afraid you'll have to make custom UIView with drawRect: method for that – Vladimir Oct 10 '11 at 20:12
  • 1
    If I do this, and on top of this view I have an animation, like a modal UINavigationController dismissing, I see a lot of glitches happening, it's hard to describe. If I deactivate the borders, everything goes back to normal. – Nicu Surdu Jun 16 '12 at 13:42
  • @NicolaeSurdu, setting border may indeed be a performance problem, in that case you can use your approach with custom view – Vladimir Jun 16 '12 at 16:47
  • 5
    Just a heads up for others. Xcode suggests bridging UIColor to CGColorRef as `__bridge CGColorRef`. This does not work. It needs to be `[UIColor blackColor].CGColor` as mentioned in answer. – GoodSp33d Jul 10 '14 at 05:05
  • 7
    `#import ` is no longer needed. – meaning-matters Nov 15 '14 at 14:06
43

Xcode 6 update

Since Xcode's newest version there is a better solution to this:

With @IBInspectable you can set Attributes directly from within the Attributes Inspector.

My Custom View @IBInspectable Attributes

This sets the User Defined Runtime Attributes for you:

enter image description here

There are two approaches to set this up:

Option 1 (with live updating in Storyboard)

  1. Create MyCustomView.
  2. This inherits from UIView.
  3. Set @IBDesignable (this makes the View update live).*
  4. Set your Runtime Attributes (border, etc.) with @IBInspectable
  5. Change your Views Class to MyCustomView
  6. Edit in Attributes Panel and see changes in Storyboard :)

`

@IBDesignable
class MyCustomView: UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

* @IBDesignable only works when set at the start of class MyCustomView

Option 2 (not working since Swift 1.2, see comments)

Extend your UIView Class:

extension UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

This way, your default View always has those extra editable fields in Attributes Inspector. Another advantage is that you don't have to change the class to MycustomView every time. However, one drawback to this is that you will only see your changes when you run your app.

MMachinegun
  • 3,044
  • 2
  • 27
  • 44
17

You can also create border with the color of your wish..

view.layer.borderColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0].CGColor;

*r,g,b are the values between 0 to 255.

rohan-patel
  • 5,772
  • 5
  • 45
  • 68
  • 6
    It's worth noting that `r`, `g` and `b` should probably be floats; the divisors should also be floats: `r / 255.0`. –  Jun 22 '12 at 08:53
  • no, C syntax is not as You say. r, g and b can be int, as C (and objC IS C) promotions will cast int r=128 to double when making: r/255.0. By the way You got double, and Clang will cast to CGFloat. – ingconti Jan 28 '18 at 14:54
10

Add following @IBInspectables in UIView extension

extension UIView {

  @IBInspectable var borderWidth: CGFloat {
    get {
      return layer.borderWidth
    }
    set(newValue) {
      layer.borderWidth = newValue
    }
  }

  @IBInspectable var borderColor: UIColor? {
    get {
      if let color = layer.borderColor {
        return UIColor(CGColor: color)
      }
      return nil
    }
    set(newValue) {
      layer.borderColor = newValue?.CGColor
    }
  }
}

And then you should be able to set borderColor and borderWidth attributes directly from Attribute inspector. See attached image

Attributes Inspector

Bikramjit Singh
  • 101
  • 1
  • 2
9
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor
Roopendra
  • 7,674
  • 16
  • 65
  • 92
shaiju mathew
  • 433
  • 5
  • 8
8

When I use Vladimir's CALayer solution, and on top of the view I have an animation, like a modal UINavigationController dismissing, I see a lot of glitches happening and having drawing performance issues.

So, another way to achieve this, but without the glitches and performance loss, is to make a custom UIView and implement the drawRect message like so:

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}
Nicu Surdu
  • 8,172
  • 9
  • 68
  • 108
  • @Krish You store the color in a variable and when you need to change the border color, you change the variable value and call `setNeedsDisplay` on the view. This will force the redraw of the UIView and implicitly will re-call `drawRect`. Not tested, tho ... – Nicu Surdu Jul 26 '12 at 11:27
7

Try this code:

view.layer.borderColor =  [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];
Vikram Biwal
  • 2,618
  • 1
  • 25
  • 36
4

I wouldn't suggest overriding the drawRect due to causing a performance hit.

Instead, I would modify the properties of the class like below (in your custom uiview):

  - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
      self.layer.borderWidth = 2.f;
      self.layer.borderColor = [UIColor redColor].CGColor;
    }
  return self;

I didn't see any glitches when taking above approach - not sure why putting in the initWithFrame stops these ;-)

DEzra
  • 2,978
  • 5
  • 31
  • 50
4

I wanted to add this to @marczking's answer (Option 1) as a comment, but my lowly status on StackOverflow is preventing that.

I did a port of @marczking's answer to Objective C. Works like charm, thanks @marczking!

UIView+Border.h:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface UIView (Border)

-(void)setBorderColor:(UIColor *)color;
-(void)setBorderWidth:(CGFloat)width;
-(void)setCornerRadius:(CGFloat)radius;

@end

UIView+Border.m:

#import "UIView+Border.h"

@implementation UIView (Border)
// Note: cannot use synthesize in a Category

-(void)setBorderColor:(UIColor *)color
{
    self.layer.borderColor = color.CGColor;
}

-(void)setBorderWidth:(CGFloat)width
{
    self.layer.borderWidth = width;
}

-(void)setCornerRadius:(CGFloat)radius
{
    self.layer.cornerRadius = radius;
    self.layer.masksToBounds = radius > 0;
}

@end
spencery2
  • 511
  • 2
  • 10
2

@IBInspectable is working for me on iOS 9 , Swift 2.0

extension UIView {

@IBInspectable var borderWidth: CGFloat {
get {
        return layer.borderWidth
    }
    set(newValue) {
        layer.borderWidth = newValue
    }
}

@IBInspectable var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set(newValue) {
        layer.cornerRadius = newValue
    }
}

@IBInspectable var borderColor: UIColor? {
    get {
        if let color = layer.borderColor {
            return UIColor(CGColor: color)
        }
        return nil
    }
    set(newValue) {
        layer.borderColor = newValue?.CGColor
    }
}
anhtran
  • 21
  • 2
1

If you didn't want to edit the layer of a UIView, you could always embed the view within another view. The parent view would have its background color set to the border color. It would also be slightly larger, depending upon how wide you want the border to be.

Of course, this only works if your view isn't transparent and you only want a single border color. The OP wanted the border in the view itself, but this may be a viable alternative.

Matt Becker
  • 2,338
  • 1
  • 28
  • 36
1

item's border color in swift 4.2:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_lastOrderId") as! Cell_lastOrder
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.cornerRadius = 10
Akhrua
  • 11
  • 3
0

[self.view.layer setBorderColor: [UIColor colorWithRed:0.265 green:0.447 blue:0.767 alpha:1.0f].CGColor];

Nitin singh
  • 21
  • 2
  • 6
0

If you want to add different border on different sides, may be add a subview with the specific style is a way easy to come up with.

Yuanfei Zhu
  • 751
  • 5
  • 16