从 xib 加载自定义视图后,IBOutlet 属性为 nil
IBOutlet properties nil after custom view loaded from xib
IBOutlets 发生了一些奇怪的事情。
在代码中我尝试访问此属性,但它们是 nil
。代码:
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
}
}
您是如何从控制器启动视图的?像这样:
var view = CustomKeyboard.keyboard()
self.view.addSubview(view)
这是预料之中的,因为在调用初始化程序时 IBOutlet 尚未分配。您不需要 commonInit,只需按如下方式覆盖 awakeFromNib:
override func awakeFromNib() {
super.awakeFromNib()
print(aButt)
}
您的笔尖可能未连接。我的解决方案非常简单。在你项目的某处(我创建了一个名为 UIViewExtension.swift 的 class),使用这个方便的 connectNibUI 方法添加 UIView 的扩展。
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)
}
}
}
现在您可以在任何视图上调用此方法,在您的 init 方法中,执行以下操作:
override init(frame: CGRect) {
super.init(frame: frame)
connectNibUI()
}
假设您尝试了连接 IBOutlets 的标准故障排除步骤,试试这个:
显然,在某些运行时情况下,您需要禁用从 nib 唤醒。
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
guard subviews.isEmpty else { return self }
return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
}
在@ScottyBlades 的基础上,我制作了这个子类:
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))"
}
您可能没有提到 xib 的 FileOwner。
在文件所有者中提及其 class 而不是在视图身份检查器中。
IBOutlets 发生了一些奇怪的事情。
在代码中我尝试访问此属性,但它们是 nil
。代码:
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
}
}
您是如何从控制器启动视图的?像这样:
var view = CustomKeyboard.keyboard()
self.view.addSubview(view)
这是预料之中的,因为在调用初始化程序时 IBOutlet 尚未分配。您不需要 commonInit,只需按如下方式覆盖 awakeFromNib:
override func awakeFromNib() {
super.awakeFromNib()
print(aButt)
}
您的笔尖可能未连接。我的解决方案非常简单。在你项目的某处(我创建了一个名为 UIViewExtension.swift 的 class),使用这个方便的 connectNibUI 方法添加 UIView 的扩展。
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)
}
}
}
现在您可以在任何视图上调用此方法,在您的 init 方法中,执行以下操作:
override init(frame: CGRect) {
super.init(frame: frame)
connectNibUI()
}
假设您尝试了连接 IBOutlets 的标准故障排除步骤,试试这个:
显然,在某些运行时情况下,您需要禁用从 nib 唤醒。
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
guard subviews.isEmpty else { return self }
return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
}
在@ScottyBlades 的基础上,我制作了这个子类:
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))"
}
您可能没有提到 xib 的 FileOwner。 在文件所有者中提及其 class 而不是在视图身份检查器中。