IBOutlet properties nil after custom view loaded from xib
Solution 1
That's expected, because the IBOutlet(s) are not assigned by the time the initializer is called. You don't need the commonInit, just an override of awakeFromNib as follows:
override func awakeFromNib() {
super.awakeFromNib()
print(aButt)
}
Solution 2
Assuming you tried the standard troubleshooting steps for connecting IBOutlets, try this:
Apparently, you need to disable awake from nib in certain runtime cases.
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
guard subviews.isEmpty else { return self }
return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
}
Solution 3
Your nib may not be connected. My solution is quite simple. Somewhere in your project (I create a class called UIViewExtension.swift), add an extension of UIView with this handy connectNibUI method.
extension UIView {
func connectNibUI() {
let nib = UINib(nibName: String(describing: type(of: self)), bundle: nil).instantiate(withOwner: self, options: nil)
let nibView = nib.first as! UIView
nibView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(nibView)
//I am using SnapKit cocoapod for this method, to update constraints. You can use NSLayoutConstraints if you prefer.
nibView.snp.makeConstraints { (make) -> Void in
make.edges.equalTo(self)
}
}
}
Now you can call this method on any view, in your init method, do this:
override init(frame: CGRect) {
super.init(frame: frame)
connectNibUI()
}
Solution 4
Building on @ScottyBlades, I made this subclass:
class UIViewXib: UIView {
// I'm finding this necessary when I name a Xib-based UIView in IB. Otherwise, the IBOutlets are not loaded in awakeFromNib.
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
guard subviews.isEmpty else { return self }
return Bundle.main.loadNibNamed(typeName(self), owner: nil, options: nil)?.first
}
}
func typeName(_ some: Any) -> String {
return (some is Any.Type) ? "\(some)" : "\(type(of: some))"
}
Gralex
Updated on November 02, 2020Comments
-
Gralex over 3 years
Something strange going on with IBOutlets.
In code I've try to access to this properties, but they are
nil
. Code:class CustomKeyboard: UIView { @IBOutlet var aButt: UIButton! @IBOutlet var oButt: UIButton! class func keyboard() -> UIView { let nib = UINib(nibName: "CustomKeyboard", bundle: nil) return nib.instantiateWithOwner(self, options: nil).first as UIView } override init() { super.init() commonInit() } override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } // MARK: - Private private func commonInit() { println(aButt) // aButt is nil aButt = self.viewWithTag(1) as UIButton println(aButt) // aButt is not nil } }