问题
I'm trying to add an IBInspectable
color to UIView, so that I can set it in the storyboard and later use it in code. In this post regarding UITextField I've seen that I can take advantage of extensions and adding a computed property, but I can't make it work for UIView.
I get a crash: Failed to set (additionalColor1) user defined inspected property on (UIView): [ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key additionalColor1.
Any idea what's causing the crash and how to fix it?
Here's my code:
extension UIView {
@IBInspectable var additionalColor1: UIColor? {
return self.additionalColor1
}
}
For the reference, I'm pasting the code that can be used to set the placeholder color for UITextField (same as the above url). This works ok:
extension UITextField {
@IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string: self.placeholder != nil ? self.placeholder! : "", attributes:[NSForegroundColorAttributeName: newValue!])
}
}
}
回答1:
As mentioned in your question title
Swift extensions can only add computed properties to a type, but they cannot add stored properties.
(For more detailed information please refer to the Extension chapter in The Swift Programming Language.)
The example you posted is actually flawed — even if it has 50 upvotes on Stackoverflow at this time. If you return the value of a property itself from the property's getter you're creating a loop.
@IBInspectable var additionalColor1: UIColor? {
return self.additionalColor1
}
If you have a view
and you try to access view.additionalColor1
anywhere in your code your property's getter will be called which returns self.additionalColor1
— or with other words: it returns the property's value again — and guess how? By calling the propery's getter! (And so on...)
The example from the post you mentioned only "works" because the getter is evidently never called. It's only setting that computed property placeHolderColor
that changes another stored property, namely the text field's attributedPlaceholder
.
So while you can add computed properties to an existing class through an extension you can never think of it as a concrete value that's stored somewhere. Computed properties may only be used to somehow transform the value you assign to it and store the result in existing stored properties.
回答2:
How is your additionalColor
going to be used?
I had to do something similar to this recently, but in my case I was always applying the extra value right away.
For example, I wanted to create a button that looked like a parallelogram. So, I wanted a way to put in a value in the Storyboard, which would apply a CGAffineTransform. I'm not really storing the skew value, just using to change what the thing looks like. Then, in the get
, I'm passing back the value from the view's affineTransform
routine.
@IBInspectable var skewOffset: Float {
set(newSkewOffset) {
let affineTransform : CGAffineTransform = CGAffineTransform(a: 1.0, b: 0.0, c: CGFloat(newSkewOffset), d: 1.0, tx: 0.0, ty: 0.0)
layer.setAffineTransform(affineTransform)
}
get {
return Float(layer.affineTransform().c)
}
}
So, I'm not storing skewOffset
, I'm applying it, and I know how I can look it up later, if I need to get it.
来源:https://stackoverflow.com/questions/42334264/cant-set-ibinspectable-computed-property-in-uiview