So I am implementing a custom "chooser" toolbar, like the iOS equivalent of a radio button set (UISegmentedControl
). Just a horizontal bar divided into options.
To do this, I created a subclass of UIControl
called SegmentedControl
and implemented custom drawing. However, with such a view, I need the option to set what the available options are. I could have just accessed the view from the controller's viewDidLoad()
and set those there, but I like using the interface builder for that kind of stuff.
So I discovered this wonderful thing called "User Defined Runtime Attributes." I created a String
attribute with a key buttonValues
and set a value (this is a simple Male/Female chooser so I went with "Male|Female"). I found out that you can access these values using the function self.valueForKey()
and pass in the key. I made a parser to turn that string into an array and then added functionality for the drawRect()
function to use the array to set up the buttons.
When I ran the app, I got an error about "Key Value Coding-compliance."
So I looked that up, and I found out that the class has to have backing variables to store the attributes. So fine, I added an instance variable called buttonValues
and initialized it to ""
. Now the app runs fine but the value comes out empty from the self.valueForKey()
function. I looked up tutorials on how to set up user defined runtime attributes but they don't go into enough detail. They talk about Key Value Coding-compliance like it's something I should just know.
I would like to know exactly what I must do for this to work properly, in gory detail.
For your purposes you can use either user-defined runtime attributes or expose your class and properties as editable in Interface Builder. Either way, you'll want to declare your properties as implicitly unwrapped Optional variables -- IBOutlets
are created the same way. If you need to make other changes once your properties have a value, give them didSet
property observers. The properties will be at their default value during initialization (or nil
if no default was set) and set when the view is added to a superview.
This works more or less like you've described above -- here's the simplest version:
class LabeledView : UIView {
var viewLabel: String! {
didSet {
println("didSet viewLabel, viewLabel = \(self.viewLabel)")
}
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
println("init with coder, viewLabel = \(self.viewLabel)")
}
}
Then set the viewLabel
attribute to "Hello" on the view in your storyboard, like so:
When you build & run, the console will show that the property is being set correctly:
init with coder, viewLabel = nil
didSet viewLabel, viewLabel = Hello
This gives your custom view a much nicer interface in IB -- set the @IBDesignable
attribute on your class and @IBInspectable
attributes on each property. Here's the same class:
@IBDesignable class LabeledView : UIView {
@IBInspectable var viewLabel: String!
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
}
Now you can set your inspectable properties at the top of the Attributes Inspector in Interface Builder:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With