193

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

matteo.cajani
  • 2,325
  • 2
  • 17
  • 17
  • Check this [http://stackoverflow.com/a/28854514/3177007](http://stackoverflow.com/a/28854514/3177007) – Mohamed Jaleel Nazir Mar 04 '15 at 12:33
  • 1
    Just in case anyone comes from Google like I did. To see those changes reflect in IB you just need to create a subclass of UIView and assign it to whatever View you want to manipulate in IB. – Kanongata Aug 27 '17 at 02:38

10 Answers10

396

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

Sunil Targe
  • 7,009
  • 5
  • 42
  • 71
Rich86man
  • 6,377
  • 2
  • 24
  • 27
  • 3
    To you and Peter DeWeese: I use Xcode 4.6.3 and I can set keypath type to "Color" without impleting a CALayer interface –  Sep 09 '13 at 13:06
  • Thanks for the heads up! They must have fixed that in a newer version of xcode than I had at the time – Rich86man Sep 18 '13 at 21:26
  • 41
    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 '14 at 22:33
  • Make sure you have included the QuartzCore framework or it won't work. – Ben Jul 30 '14 at 12:48
  • 12
    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. – Andy Ibanez Sep 22 '14 at 19:31
  • layer.borderColor does not seem to work in IB (Xcode 6). Again guessing that its because its a UIColor not a CGColor. – lostintranslation Nov 11 '14 at 17:03
  • Number types for cornerRadius, borderWidth works fine. layer.borderColor does not work because it is not CGColor. – vijayst Nov 24 '14 at 06:38
  • 1
    Here is my solution from within IB in storyboard, all working (even Color) :) http://stackoverflow.com/a/29074130 – MMachinegun Mar 16 '15 at 10:15
  • 3
    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"! – Peter Kreinz Aug 15 '15 at 18:54
  • If it does not work, make sure you don't have `layer.borderColor` or `borderColor` under `User Defined Runtime Attributes` – Yevhen Dubinin Jan 08 '16 at 18:08
  • 1
    I came here looking for why my corners wouldn't bend, only to find out I had misspelled `cornerRadius` in the inspector :) – Nicolas Miari Mar 30 '16 at 01:25
  • Hi everyone - just wanted to point out that this answer is only valid in conjunction with the answer from @Peter DeWeese – etayluz Aug 18 '16 at 19:10
  • 5
    Also, don't forget to check the "clip to bounds" checkbox to have the cornerRadius working. – Pierre-Olivier Simonard Aug 08 '18 at 15:08
  • 3
    Should be `layer.borderUIColor` – Aviv Ben Shabat Sep 04 '18 at 20:17
188

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 {
    var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.CGColor
        }

        get {
            return UIColor(CGColor: self.borderColor!)
        }
    }
}

In Swift 3.0:

extension CALayer {
    var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.cgColor
        }

        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}
Jeremy
  • 519
  • 1
  • 6
  • 22
Peter DeWeese
  • 17,664
  • 8
  • 75
  • 98
  • 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 05 '13 at 08:22
  • CALayer(myCategory) is a category, that is, it adds its methods to an existing class that is implemented elsewhere. In this case CALayer is included with the framework and I am just adding the borderUIColor property to it. Your way of implementing this will not work, although I suppose that you could add the property to your view controller and have it update the layer instead. – Peter DeWeese Sep 05 '13 at 15:45
  • 2
    @PeterDeWeese great answer!=) – c-villain Sep 04 '14 at 22:07
  • To get it work you should set borderWidth type to String, not Number. Pretty confusing. – lumenela Oct 19 '14 at 06:09
  • 1
    You actually can use Number with borderWidth and accept an NSNumber. It works fine. – Peter DeWeese Oct 19 '14 at 17:18
  • We cannot add variable in category. I am not getting how this whole thing is working? Can you please explain, I am confused? – Nuzhat Zari Nov 05 '14 at 06:51
  • @Nuzhat Zari, The variable already exists in CALayer, and this is simply adding a wrapper around it. No variable is created by the category! – Peter DeWeese Nov 05 '14 at 13:55
  • I have applied layer.borderUIColor in User defined runtime attributes...it's not working in runtime also. – Yalamandarao Feb 26 '15 at 08:27
  • @Singapore, try setting breakpoints in your category methods to make sure it is calling them. As a note, you can simply proxy it from UIView instead of CALayer. – Peter DeWeese Feb 27 '15 at 13:32
  • 1
    This is definitely the best solution in my opinion to solve the issue of BorderColor. Fantastic use of categories! – EricWasTaken Jul 04 '15 at 20:15
  • If anyone's wondering about the Swift solutions, it works! 01. Create a Cocoa Touch Class file: UIButton. 02. Associate the IB Button with your newly created class in IB. 03. Add the extension to the newly created class (above code). – Jonathan Soifer Sep 03 '16 at 20:30
  • 1
    Worked in Swift ! – KOTIOS Dec 08 '16 at 11:17
  • In case if swift doesn't work for someone, try this https://stackoverflow.com/a/46554726/618994 – Vignesh Oct 07 '20 at 09:36
90

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.

Axel Guilmin
  • 10,343
  • 7
  • 49
  • 59
57

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.

iHulk
  • 4,683
  • 2
  • 27
  • 38
  • 2
    Complement it with IB_DESIGNABLE to make IB redraw your custom view using the drawRect: method https://developer.apple.com/library/ios/recipes/xcode_help-IB_objects_media/Chapters/CreatingaLiveViewofaCustomObject.html#//apple_ref/doc/uid/TP40014224-CH41-SW1 – txulu Aug 25 '15 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 '16 at 21:49
  • @user1618612 it has nothing to do with the resolution, it is just setting normal layer properties. – iHulk Dec 09 '16 at 06:43
12

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
        }
    }
}
RamwiseMatt
  • 2,087
  • 3
  • 9
  • 22
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

Zayin Krige
  • 2,931
  • 1
  • 29
  • 31
4

If you want to save time, just use two UIViews on top of each other, the one at the back being the border color, and the one in front smaller, giving the bordered effect. I don't think this is an elegant solution either, but if Apple cared a little more then you shouldn't have to do this.

MLQ
  • 12,329
  • 12
  • 79
  • 130
0

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

Sunil Targe
  • 7,009
  • 5
  • 42
  • 71
-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
swiftBoy
  • 33,793
  • 26
  • 129
  • 124
  • The question is very specific and ask how to do it from the Interface Builder. Your answer is irrelevant. – Shinnyx Oct 24 '19 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.

user28434'mstep
  • 5,401
  • 1
  • 16
  • 31
Sneha Patil
  • 59
  • 1
  • 7