I'm trying to understand how to properly subclass view which is loaded from a xib in Swift.
I've got TitleDetailLabel
class which is subclass of UIControl
. This class has titleLabel
and detailLabel
outlets which are UILabel
s.
class TitleDetailLabel: UIControl {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var detailLabel: UILabel!
override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
return NTHAwakeAfterUsingCoder(aDecoder, nibName: "TitleDetailLabel")
}
func setTitle(text: String) {
self.titleLabel.text = text
}
func setDetailText(text: String) {
self.detailLabel.text = text
}
}
XIB structure:
- Placeholders
- File's Owner:
NSObject
(not changed) - First Responder
- File's Owner:
- Title Detail Label -
UIView
-TitleDetailLabel
class- Label -
UILabel
- title label - Label -
UILabel
- detail label
- Label -
In Storyboard I've got view controller and placeholder - simple UIView
object with constraints.
I've created extension to UIView
class to simplify swapping placeholder with object I am interested in. It works good with this TitleDetailLabel
class. Here is how it looks:
extension UIView {
public func NTHAwakeAfterUsingCoder(aDecoder: NSCoder, nibName: String) -> AnyObject? {
if (self.subviews.count == 0) {
let nib = UINib(nibName: nibName, bundle: nil)
let loadedView = nib.instantiateWithOwner(nil, options: nil).first as UIView
/// set view as placeholder is set
loadedView.frame = self.frame
loadedView.autoresizingMask = self.autoresizingMask
loadedView.setTranslatesAutoresizingMaskIntoConstraints(self.translatesAutoresizingMaskIntoConstraints())
for constraint in self.constraints() as [NSLayoutConstraint] {
var firstItem = constraint.firstItem as UIView
if firstItem == self {
firstItem = loadedView
}
var secondItem = constraint.secondItem as UIView?
if secondItem != nil {
if secondItem! == self {
secondItem = loadedView
}
}
loadedView.addConstraint(NSLayoutConstraint(item: firstItem, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
}
return loadedView
}
return self
}
}
I decided to create BasicTitleDetailLabel
subclass of TitleDetailLabel
class to keep there some configuration code and other stuff.
class BasicTitleDetailLabel: TitleDetailLabel {
override func awakeFromNib() {
super.awakeFromNib()
self.setup()
}
override init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
private func setup() {
self.titleLabel.textColor = UIColor.NTHCadetGrayColor()
self.detailLabel.textColor = UIColor.NTHLinkWaterColor()
}
}
But application crashes every time after I changed class of this placeholder from TitleDetailLabel
to BasicTitleDetailLabel
.
App crashes because titleLabel
and detailLabel
are nil.
How can I properly use this TitleDetailLabel
class with xib and how to subclass this correctly? I don't want to create another xib which looks the same like the first one to use subclass.
Thanks in advance.