I'm having some trouble with visualise my custom table view cell in the interface builder.
Does anyone know how to make a @Designable
table view cell?
When I import my custom table view cell in a storyboard with a tableview, only the background color is working. When I try to set the text of the label inside my table view cell, the interface builder crashes.
My setup is called from the following methods:
- override public init(style: UITableViewCellStyle, reuseIdentifier: String?)
- required public init?(coder aDecoder: NSCoder)
I think it's because my label isn't initialised at this moment?
Code:
import UIKit
@IBDesignable class ProgressHeaderTableViewCell: UITableViewCell {
@IBOutlet weak var headerLabel: UILabel!
// MARK: - View methods
override public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.setupNib()
}
// MARK: - NSCoding
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setupNib()
}
func setupNib(){
self.backgroundColor = UIColor.blue
// self.headerLabel.text = "Hello world"
}
}
Updated code:
import UIKit
@IBDesignable class CustomTableView: UITableViewCell {
@IBOutlet weak var headerLabel: UILabel!
// MARK: - View methods
override func prepareForInterfaceBuilder() {
self.awakeFromNib()
}
override public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//check that there are no current subviews
if self.subviews.count == 0 {
self.setupNib()
}
}
// MARK: - NSCoding
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//check that there are no current subviews
if self.subviews.count == 0 {
self.setupNib()
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.backgroundColor = UIColor.blue
if headerLabel != nil {
self.headerLabel.text = "Hello world"
}
}
func setupNib(){
let bundle = Bundle(for: CustomTableView.self)
guard let customView = bundle.loadNibNamed("CustomTableView",owner: self, options: nil)?.first as? CustomTableView else {
return
}
customView.frame = self.bounds
self.addSubview(customView)
}
}
Thank you!
I think there are a couple of possible issues you can look into here. First, whenever you create a custom view you will need to associate it with the xib file name.
func setupNib(){
let bundle = Bundle(for: ProgressHeaderTableViewCell.self)
guard let customView = bundle.loadNibNamed("NAME_OF_XIB_FILE_GOES_HERE",owner: self, options: nil)?.first as? ProgressHeaderTableViewCell else {
return
}
customView.frame = self.bounds
self.addSubview(customView)
}
Also, whenever I work with xib files, I do any view setup within the awakeFromNib()
method after checking to make sure one of the expected elements is not nil.
override func awakeFromNib() {
if headerLabel != nil {
self.backgroundColor = UIColor.blue
self.headerLabel.text = "Hello world"
}
}
Finally, I've only been able to get IBDesignables to work when I wrap the setup functions with the a check that there are no current subviews:
override public init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//check that there are no current subviews
if self.subviews.count == 0 {
self.setupNib()
}
}
// MARK: - NSCoding
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//check that there are no current subviews
if self.subviews.count == 0 {
self.setupNib()
}
}
P.S When I was learning this, I found this blog post super helpful. You may want to read through it yourself to get a handle on IBDesignable and custom views. http://supereasyapps.com/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6