Reputation: 4340
I want to create a custom palette in IB where you can set colors, and if a color changes in that palette it propagates through the views. I've seen this approach http://natashatherobot.com/xcode-color-palette/, but if in the future, a color of the palette changes, you have to go to every view on the project and change that color. I tried also doing an @IBInspectable but you can't have enums (so you can map an enum to a color). I know i can just define the colors by code and then having an outlet, but the problem is I a have tons of views that I need to subclass just for changing a color like this:
class TestCommonView: CommonView {
@IBOutlet weak var borderView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
borderView.backgroundColor = Colors.fabrica.pastel
}
}
Any ideas?
Upvotes: 2
Views: 1182
Reputation: 48524
Reconsidering this statement:
I tried also doing an @IBInspectable but you can't have enums (so you can map an enum to a color).
You can bridge over an @IBInspectable
enum
using Int
this way:
enum ColorPalette:Int {
case clear = 0
case teal = 1
case plum = 2
case foam = 3
}
var tincture:ColorPalette = .clear
In code, access self.tincture
, which is the enum
you are after.
In Interface Builder, use tinctureAdapter
which is an Int
, and therefore a de-facto @IBInspectable
of type enum.
// Stored IB property
@available(*, unavailable, message="Use tincture programmatically")
@IBInspectable var tinctureAdapter:Int {
get {
return self.tincture.rawValue
}
set {
self.tincture = ColorPalette:Int(rawValue: newValue) ?? .clear
}
}
It may be useful to place this code in a UIColor
class Extension. Using the bridge approach, you could also use @Donamite plain-English strings in IB.
Swift 3 Example
@IBDesignable class ColorSwatchView: UIView {
enum ColorPalette: String {
case Thistle = "thistle"
case Plum = "plum"
case Olive = "olive"
case Iris = "iris"
case Clear = "clear"
}
let namedColors = [
"thistle": UIColor(red: 216/255, green: 191/255, blue: 216/255, alpha: 1),
"plum" : UIColor(red: 221/255, green: 160/255, blue: 221/255, alpha: 1),
"olive" : UIColor(red: 128/255, green: 128/255, blue: 0/255, alpha: 1),
"iris" : UIColor(red: 3/255, green: 180/255, blue: 200/255, alpha: 1)
]
var tincture:ColorPalette = .Clear
// Stored IB property
@available(*, unavailable, message: "Use tincture programmatically")
@IBInspectable var tinctureName: String? {
willSet {
if let color = ColorPalette(rawValue: newValue?.lowercased() ?? "") {
tincture = color
}
}
}
}
Interface Builder
Make your custom view a child of ColorSwatchView
.
Programmatically
override func draw(_ rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()
ctx?.saveGState()
let uiColor = namedColors[tincture.rawValue] ?? UIColor.clear
ctx?.setFillColor(uiColor.cgColor)
ctx?.fill(bounds)
ctx?.restoreGState()
}
► Find this solution on GitHub and additional details on Swift Recipes.
Upvotes: 2