UIView's border color in Interface builder doesn't work?
Solution 1
It's possible to do this, but it's not a built-in feature. This is because the Color
type in the User Defined Runtime Attributes panel creates a UIColor
, but layer.borderColor
holds a CGColorRef
type. Unfortunately, there's no way to assign a CGColorRef
type in Interface Builder.
However, this is possible through a proxy property. See Peter DeWeese's answer to a different question for a possible solution to this problem. His answer defines a category that allows a proxy color to be set through Interface Builder.
Solution 2
You have to create Category for CALayer:
CALayer+UIColor.h
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer(UIColor)
// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;
@end
CALayer+UIColor.m
#import "CALayer+UIColor.h"
@implementation CALayer(UIColor)
- (void)setBorderUIColor:(UIColor*)color {
self.borderColor = color.CGColor;
}
- (UIColor*)borderUIColor {
return [UIColor colorWithCGColor:self.borderColor];
}
@end
And then in User Defined Runtime attributes You can use it as it is on image below:
For Swift it is much more simple:
import QuartzCore
extension CALayer {
@IBInspectable var borderUIColor: UIColor? {
get {
guard let borderColor = borderColor else { return nil }
return UIColor(cgColor: borderColor)
}
set {
borderColor = newValue?.cgColor
}
}
}
Then in Xcode you can use it like this:
Once you choose sth it is automatically added to your runtime attributes:
Solution 3
Copy and paste this class:
import UIKit
@IBDesignable class BorderView : UIView {
@IBInspectable var borderColor: UIColor = .clear {
didSet {
layer.borderColor = borderColor.cgColor
}
}
@IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
@IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
Now in Interface Builder, go to the Identity inspector and set your view as a CustomView class.
After that, check out your Attributes Inspector:
No need to mess around with user defined runtime attributes anymore. And your changes will also show up on the canvas!
Solution 4
My two cents for porting Bartłomiej Semańczyk's answer to Swift:
Create an extension for CALayer in your view controller:
import UIKit
extension CALayer {
func borderUIColor() -> UIColor? {
return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
}
func setBorderUIColor(color: UIColor) {
borderColor = color.CGColor
}
}
Solution 5
Use IBDesignable instead of Runtime Attributes it is more clear.
Put this code in any class and edit the properties direct on the storyboard.
import UIKit
@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
}
}
}
Comments
-
0xSina over 2 years
I am trying to set up a view's layer properties via IB. Everything works except for color of the border (property
layer.borderColor
):I remember running into this problem a year ago and I ended up doing it programatically. And still, I can do this programmatically, but I am curious why the
layer.borderColor
property never works via interface builder. I don't want to importQuartzCore
, and then write extra line of code just because of this, seems like an overkill.-
Admin about 11 years"write extra line of code just because of this, seems like an overkill" - your app must be containing at most 10 lines of code then (with the C standard headers included) :P
-
0xSina about 11 years@H2CO3 lol...i just don't like writing code that i don't have to
-
chuthan20 about 11 yearsI've made this mistake in the past.. I hope you are aware of it.. otherwise check the first answer from this: stackoverflow.com/questions/3980251/…
-
Peter DeWeese almost 11 yearsYou can do this with a proxy property! See my answer in stackoverflow.com/questions/12301256/…
-
-
0xSina about 11 yearsHmmmm...not @ my desktop so will experiment with that, but if I set masksToBounds to NO, then I can't have UIImageView rounded/corner radius :(
-
storoj over 10 yearsi think there is no need to use associated objects because something may happen and your borderColor will be out of sync with layer.borderColor. just return [UIColor colorWithCGColor:self.layer.borderColor]
-
bainfu over 10 yearsYou're absolutely right @storoj. It's a pattern we use for adding properties and being able to store them using categories. It's misapplied here.
-
Lloyd Sargent almost 9 yearsThis is the easiest solution and one that I implemented. Downside is you can forget it's there (it's only a few lines!).
-
raven_raven almost 8 yearsWhy borderUIColor property is
assign
instead ofstrong
? It's an object type, doesn't this lead to a problem? -
Haligen almost 8 yearsThis saves a major headache when you're applying these to several items. Slick little tidbit.
-
etayluz over 7 yearsI'm sorry but this doesn't work. I have just tried it myself. @IBDesignable doesn't work on extensions of UIView. stackoverflow.com/questions/29906855/…
-
Michael Shang over 7 yearsJust tried with some tiny upper/lower case problem with Swift 3.0. Shame that I did not know this before.
-
atastrophic about 7 years^ because it doesn't hold the value, it passes it on.
-
jungledev almost 7 yearsYour answer has nothing to do with the question. The poster said he knows how to do it programmatically. Also, you can see that he already set the borderWidth to be >1 in his screenshot. He asked about doing this specifically in IB.
-
Harrison Smith over 5 yearsAs of Xcode 9 & Swift 3, this actually does work at runtime. It just doesn't display the changes in the interface builder.
-
Sinto over 5 yearsPlease provide some explanation to your code & w help to fix the issue
-
KarenAnne over 5 yearsHello @Eduardo, then how will I use this in Storyboard?
-
haik.ampardjian over 2 yearsThis is actually the working solution!
-
Rafael Nobre over 2 yearsAdding an extension like this is unreliable at best. Definitely not the way to do it in 2021.