如何允许子类使用父类的nib

时间:2018-02-09 21:56:48

标签: ios xib nib

假设我有一个父视图类,它至少包含一个属性:

  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文件继承?

1 个答案:

答案 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应如下所示:

BaseView.xib