假设我有一个父视图类,该类至少包含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应该看起来像这样:

ios - 如何允许子类使用父类的 Nib-LMLPHP

10-08 01:01