假设我有一个父视图类,它至少包含一个属性:
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文件继承?
答案 0 :(得分:1)
问题是,nib中的根视图属于BaseView
类型,因此as! ChildViewA
失败。由于您无权访问nib加载器用于取消归档xib的NSKeyedUnarchiver
,因此在取消归档期间没有简单的方法来替换您自己的类。
这是一种解决方法。
不将BaseView
本身嵌入xib中。相反,将xib中的顶级视图设为普通UIView
,并将文件所有者自定义类设置为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
应如下所示: