I have a UITableViewCell which has a subview (inside its content view) which contains labels, and an image view and other properties I need to set.
This subview is set from an XIB as it is used elsewhere in the app. I am loading it into the cell with
private func setup() {
let nib = UINib.init(nibName: "AuthorHeaderView", bundle: nil)
if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
view.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(view)
view.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
view.topAnchor.constraint(equalTo: topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
}
Then, when the cell is loaded I am setting some default values in awakeFromNib()
. When I have a breakpoint there, I can see that the headerView: AuthorHeaderView
has been loaded into memory and is set up correctly, but it's labels and imageView haven't been, they are nil, and thus it crashes when trying to style these views.
How to do initial styling of labels and image views and everything in a sub view which is loaded via an XIB?
OK, so I found the solution out. The problem was that I hadn't added init(coder aDecoder: NSCoder)
I have a setup method that was being called from awakeFromNib, but I also needed to call it from initWithCoder.
Example:
override func awakeFromNib() {
super.awakeFromNib()
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
let nib = UINib.init(nibName: "HeaderView", bundle: nil)
if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
view.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(view)
view.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
view.topAnchor.constraint(equalTo: topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
}
Anyway, now it works perfectly. Hope this helps someone else at some stage :-)