201

Is it possible to control UIView border properties (color, thickness, etc...) directly from interface builder or I can only do it programmatically?

2

9 Answers 9

405

Actually you can set some properties of a view's layer through interface builder. I know that I can set a layer's borderWidth and cornerRadius through xcode. borderColor doesn't work, probably because the layer wants a CGColor instead of a UIColor.

You might have to use Strings instead of numbers, but it works!

layer.cornerRadius
layer.borderWidth
layer.borderColor

Update: layer.masksToBounds = true

example

Update: select appropriate Type for Keypath:

enter image description here

14
  • 4
    To you and Peter DeWeese: I use Xcode 4.6.3 and I can set keypath type to "Color" without impleting a CALayer interface
    – user2761503
    Sep 9, 2013 at 13:06
  • 45
    Unfortunately layer.borderColor can't be set this way. It's a CGColorRef, but that IB Color value type is a UIColor.
    – mrgrieves
    Feb 10, 2014 at 22:33
  • 14
    So THIS is what the user defined runtime attributes does! Haha, been writing for iOS since 2011 and I never learned what those fields were for. Thanks for this awesome answer. Sep 22, 2014 at 19:31
  • 4
    Nice, but you have to set the correct type for each property. The Type for e. g. "layer.cornerRadius" has to be set to "Number" instead of "String"! Aug 15, 2015 at 18:54
  • 6
    Also, don't forget to check the "clip to bounds" checkbox to have the cornerRadius working. Aug 8, 2018 at 15:08
191

Rich86Man's answer is correct, but you can use categories to proxy properties such as layer.borderColor. (From the ConventionalC CocoaPod)

CALayer+XibConfiguration.h:

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CALayer(XibConfiguration)

// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;

@end

CALayer+XibConfiguration.m:

#import "CALayer+XibConfiguration.h"

@implementation CALayer(XibConfiguration)

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

-(UIColor*)borderUIColor
{
    return [UIColor colorWithCGColor:self.borderColor];
}

@end

Interface Builder

layer.borderUIColor

The result will be apparent during runtime, not in Xcode.

Edit: You also need to set layer.borderWidth to at least 1 to see the border with the chosen color.

In Swift 2.0:

extension CALayer {
    @objc var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.CGColor
        }
    
        get {
            return UIColor(CGColor: self.borderColor!)
        }
    }
}

In Swift 3.0:

extension CALayer {
    @objc var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.cgColor
        }
    
        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}
12
  • I can't get this to work for me. The .m file moans about borderColor having to be borderUIColor and to fix it, after doing so it still shows warnings and the border color doesnt render at runtime. The bit that is different on mine is I have @ implementation NameOfFile, not @ implementation CALayer(NameOfFile), I dont understand the CALayer part, could you explain that more please
    – Dave Haigh
    Sep 5, 2013 at 8:22
  • 1
    You actually can use Number with borderWidth and accept an NSNumber. It works fine. Oct 19, 2014 at 17:18
  • 1
    This is definitely the best solution in my opinion to solve the issue of BorderColor. Fantastic use of categories! Jul 4, 2015 at 20:15
  • 1
    Worked in Swift !
    – KOTIOS
    Dec 8, 2016 at 11:17
  • 1
    In case if swift doesn't work for someone, try this stackoverflow.com/a/46554726/618994
    – Vignesh
    Oct 7, 2020 at 9:36
95

Similar answer to iHulk's one, but in Swift

Add a file named UIView.swift in your project (or just paste this in any file) :

import UIKit

@IBDesignable extension UIView {
    @IBInspectable var borderColor: UIColor? {
        set {
            layer.borderColor = newValue?.cgColor
        }
        get {
            guard let color = layer.borderColor else {
                return nil
            }
            return UIColor(cgColor: color)
        }
    }
    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }
    @IBInspectable var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
            clipsToBounds = newValue > 0
        }
        get {
            return layer.cornerRadius
        }
    }
}

Then this will be available in Interface Builder for every button, imageView, label, etc. in the Utilities Panel > Attributes Inspector :

Attributes Inspector

Note: the border will only appear at runtime.

13
  • @Gaurav What error do you see ? On which component (UIButton, UILabel, etc.) are you using it ? Apr 17, 2016 at 16:12
  • I can't help you without more details :( Apr 19, 2016 at 12:38
  • 2
    I was getting Interface Builder crashes with this approach until I removed @IBDesignable from the beginning of the extension. May 19, 2016 at 1:39
  • 1
    That is amazing... Thanks! I'm using XCode 8.2.1
    – bobwki
    Mar 13, 2017 at 0:34
  • 1
    Very handy and neat! Thanks! May 2, 2017 at 2:42
58

You can make a category of UIView and add this in .h file of category

@property (nonatomic) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable CGFloat borderWidth;
@property (nonatomic) IBInspectable CGFloat cornerRadius;

Now add this in .m file

@dynamic borderColor,borderWidth,cornerRadius;

and this as well in . m file

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

-(void)setBorderWidth:(CGFloat)borderWidth{
    [self.layer setBorderWidth:borderWidth];
}

-(void)setCornerRadius:(CGFloat)cornerRadius{
    [self.layer setCornerRadius:cornerRadius];
}

now you will see this in your storyboard for all UIView subclasses (UILabel, UITextField, UIImageView etc)

enter image description here

Thats it.. No Need to import category anywhere, just add the category's files in the project and see these properties in the storyboard.

3
  • 2
    Complement it with IB_DESIGNABLE to make IB redraw your custom view using the drawRect: method developer.apple.com/library/ios/recipes/…
    – txulu
    Aug 25, 2015 at 15:56
  • 3
    Thats great, If you write IB_DESIGNABLE in the .h file before the interface line, you dont need to add @dynamic line in .m
    – Jasmeet
    May 16, 2016 at 21:49
  • @user1618612 it has nothing to do with the resolution, it is just setting normal layer properties.
    – iHulk
    Dec 9, 2016 at 6:43
13

For Swift 3 and 4, if you're willing to use IBInspectables, there's this:

@IBDesignable extension UIView {
    @IBInspectable var borderColor:UIColor? {
        set {
            layer.borderColor = newValue!.cgColor
        }
        get {
            if let color = layer.borderColor {
                return UIColor(cgColor: color)
            }
            else {
                return nil
            }
        }
    }
    @IBInspectable var borderWidth:CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }
    @IBInspectable var cornerRadius:CGFloat {
        set {
            layer.cornerRadius = newValue
            clipsToBounds = newValue > 0
        }
        get {
            return layer.cornerRadius
        }
    }
}
2
  • This is a best solution for me May 22, 2018 at 3:51
  • Great Solution , Thank u
    – Ebtehal___
    Feb 25, 2019 at 11:03
7

while this might set the properties, it doesnt actually reflect in IB. So if you're essentially writing code in IB, you might as well then do it in your source code

3
  • 1
    Welcome to MVC! You view properties should never be in code! Jun 30, 2016 at 15:02
  • 2
    ^ This is not what MVC is. Feb 28, 2017 at 22:09
  • 1
    Considering that 95% of the time this code goes in the controller, it is also MVC, of course should you properly subclass or extend your view then its just configuration over coding :-) Sep 30, 2017 at 15:27
0

Its absolutely possible only when you set layer.masksToBounds = true and do you rest stuff.

-1

Storyboard doesn't work for me all the time even after trying all the solution here

So it is always perfect answer is using the code, Just create IBOutlet instance of the UIView and add the properties

Short answer :

layer.cornerRadius = 10
layer.borderWidth = 1
layer.borderColor = UIColor.blue.cgColor

Long answer :

Rounded Corners of UIView/UIButton etc

customUIView.layer.cornerRadius = 10

Border Thickness

pcustomUIView.layer.borderWidth = 2

Border Color

customUIView.layer.borderColor = UIColor.blue.cgColor
1
  • The question is very specific and ask how to do it from the Interface Builder. Your answer is irrelevant.
    – Shinnyx
    Oct 24, 2019 at 19:03
-5

Please add these 2 simple line of code:

self.YourViewName.layer.cornerRadius = 15
self.YourViewName.layer.masksToBounds = true

It will work fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.