假设我有一个父视图类,该类至少包含1个属性:
class BaseView : UIView {
@IBOutlet weak var myLabel: UILabel!
}
此类具有相应的xib文件,该文件具有从xib到myLabel属性的出口连接。
现在说我们还有一些从该类继承的子类:
class ChildView : BaseView {
func setup() {}
}
ChildView具有一些自定义逻辑,但是可以重用BaseView中的所有视图。它没有(或者我希望避免使用它)自己的相应xib文件。
我希望能够执行以下操作:
let childView = Bundle.main.loadNibNamed(String(describing: BaseView.self), owner: nil, options:nil)?.first as! ChildViewA
但这不起作用。都没有:
let childView = ChildView()
Bundle.main.loadNibNamed(String(describing: BaseView.self owner: childView, options: nil)
无论如何,是否允许子视图以类似方式从其父视图的xib文件继承?
最佳答案
问题是笔尖中的根视图类型为BaseView
,因此as! ChildViewA
失败。由于您无权访问nib加载程序用来解封xib的NSKeyedUnarchiver
,因此没有简单的方法可以在解存档期间替换您自己的类。
这是一种解决方法。
不要将BaseView
本身嵌入到xib中。而是将xib中的顶级视图设置为简单的UIView
,然后将File的Owner自定义类设置为BaseView
。然后删除所有与顶级视图的连接,并将它们设置在“文件的所有者”上。还给BaseView
一个rootViewFromNib
插座,并将其连接到根视图。
然后,给BaseView
一个初始化程序,该初始化程序加载其笔尖并将该rootViewFromNib
作为子视图添加到自身,其框架固定到BaseView
自己的bounds
。您可以使用自动调整大小来做到这一点。
最后,BaseView
应该如下所示:class BaseView: UIView {
@IBOutlet var myLabel: UILabel!
// other outlets, etc.
@IBOutlet private var rootViewFromNib: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
Bundle(for: BaseView.self).loadNibNamed("BaseView", owner: self, options: nil)
rootViewFromNib.frame = bounds
rootViewFromNib.autoresizingMask = [.flexibleWidth, .flexibleHeight]
rootViewFromNib.translatesAutoresizingMaskIntoConstraints = true
addSubview(rootViewFromNib)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
和BaseView.xib
应该看起来像这样: