Reputation: 273890
I am writing a custom view that has two labels as subviews - titleLabel
and subtitleLabel
.
I added two @IBInspectable
properties called titleText
and subtitleText
so that I can set the texts of the labels very easily in the storyboard.
class MyView : UIView {
var titleLabel: UILabel!
var subtitleLabel: UILabel!
@IBInspectable
var titleText: String? {
get { return titleLabel.text }
set {
titleLabel.text = newValue
let fontSize = // calculates appropriate font size for the text...
titleLabel.font = font.withSize(fontSize)
}
}
@IBInspectable
var subtitleText: String? {
get { return subtitleLabel.text }
set {
subtitleLabel.text = newValue
let fontSize = // calculates appropriate font size for the text...
subtitleLabel.font = font.withSize(fontSize)
}
}
override func draw(_ rect: CGRect) {
// here I make the view look prettier, irrelevant to the question
}
}
Now I need to initialise those two labels and add them as MyView
's subviews. I thought I could do this in awakeFromNib
:
override func awakeFromNib() {
titleLabel = UILabel(frame: CGRect(
x: ...,
y: ...,
width: ...,
height: ...))
self.addSubview(titleLabel)
subtitleLabel = UILabel(frame: CGRect(
x: ...,
y: ...,
width: ...,
height: ...))
self.addSubview(subtitleLabel)
}
So I added a MyView
to the storyboard and set its properties with the properties inspector and I ran the app. It crashed.
Apparently, the IBInspectable
properties are set before awakeFromNib
so the labels have not been initialised by then.
This means that I need to initialise the labels in a method that is called before the IBInspectable
properties are set.
What is a method that is called before IBInspectable
properties are set that I can override to initialise the subviews?
Upvotes: 1
Views: 74
Reputation: 130172
This might be obvious but the correct method to put such things into is the initializer.
// called when initialized from code
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
// called when initialized from storyboard/xib
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
// add subviews
}
Also, there is no real reason for optionals in your specific case:
let titleLabel: UILabel = UILabel()
You can add the labels as subviews and update frames later.
Upvotes: 2