从Swift 4中的XIB实例化时,自定义UIView为空白

时间:2018-12-03 15:19:03

标签: ios swift storyboard xib nib

我有一个试图从自定义XIB加载的自定义视图,但是加载后该视图似乎是空白的,甚至认为调试时它的大小正确。

我的调试语句显示框架具有正确的大小:

  

commonInit()
  XIB:MyCustomView
  myView框架:(0.0、0.0、320.0、568.0)
  myView ContentSize:(320.0,710.0)

这是我用来调用自定义视图的自定义VC

class MyCustomViewController: UIViewController {

    var myView : MyCustomView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myView = MyCustomView(frame: self.view.frame)

        self.view.addSubview(myView)

        updateScrollViewSize()

        print("myView Frame: \(myView.frame)")
        print("myView ContentSize: \(myView.contentView.contentSize)")

    }

    func updateScrollViewSize () {
        var contentRect = CGRect.zero
        for view in myView.contentView.subviews {
            contentRect = contentRect.union(view.frame)
        }
        myView.contentView.contentSize = CGSize(width: myView.contentView.frame.size.width, height: contentRect.size.height + 5)
    }
}

有一个XIB,其文件所有者为 MyCustomView ,并且所有插座均已正确连接。

class MyCustomView: UIView {

     let kCONTENT_XIB_NAME = "MyCustomView"

    @IBOutlet var contentView: UIScrollView!

    @IBOutlet weak var lbl_datein: UILabel!
    //.. A bunch of other GUI elements for the scrollview
    @IBOutlet weak var text_location: UITextField!


    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    func commonInit() {
        print(#function)
        print("XIB: \(kCONTENT_XIB_NAME)")

        Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
        contentView.addSubview(self)
        contentView.frame = self.bounds
        contentView.backgroundColor = .blue
    }
}

有人在尝试加载视图时看到我做错了什么吗

3 个答案:

答案 0 :(得分:0)

我将使用扩展程序发布您所做的替代选择。

extension UIView {

    @discardableResult
    func fromNib<T : UIView>(_ nibName: String? = nil) -> T? {
        let bundle = Bundle(for: type(of: self))
        guard let view = bundle.loadNibNamed(nibName ?? String(describing: type(of: self)), owner: self, options: nil)?[0] as? T else {
            return nil
        }
        view.translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(view)
        view.autoPinEdgesToSuperviewEdges()
        return view
    }
}

*请注意,我正在使用PureLayout进行方便的自动布局管理,即使您不使用PureLayout,也可以自己手动应用约束。

使用上述所有操作,只需从init调用以下内容;

fromNib()

*最后的注释。自定义视图名称必须与笔尖名称匹配,否则,您必须通过Nib函数将笔尖名称传递给您。

您现在有了更多可重用的东西。

答案 1 :(得分:0)

我无法获取它来运行复制/粘贴代码。也许缺少一些设置,但是我很难理解它应该如何工作。问题中的原始代码在此行崩溃:

contentView.addSubview(self)

因为当您拥有IBOutlets时,如果您使用nil进行初始化,它们将始终为MyCustomView(frame: self.view.frame)。它必须调用initWithCoder函数。

这里发生了很多事情,但这就是我要这样做的方式:

class MyCustomViewController: UIViewController {

    var myView: MyCustomView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView

        self.view.addSubview(myView)

        updateScrollViewSize()

        print("myView Frame: \(myView.frame)")
        print("myView ContentSize: \(myView.contentView.contentSize)")

    }

    func updateScrollViewSize () {
        var contentRect = CGRect.zero
        for view in myView.contentView.subviews {
            contentRect = contentRect.union(view.frame)
        }
        myView.contentView.contentSize = CGSize(width: myView.contentView.frame.size.width, height: contentRect.size.height + 5)
    }

}

class MyCustomView: UIView {

    let kCONTENT_XIB_NAME = "MyCustomView"

    @IBOutlet var contentView: UIScrollView!

    @IBOutlet weak var lbl_datein: UILabel!
    //.. A bunch of other GUI elements for the scrollview
    @IBOutlet weak var text_location: UITextField!

}

我假设笔尖中的顶级对象属于MyCustomView类,这将导致很多奇怪的事情。 loadNibNamed将调用init?(coder aDecoder: NSCoder),因此理想情况下,您首先只是从视图控制器而不是自定义视图对象中调用它即可。

关于“无法将自己添加为子视图”错误,我在运行时没有看到该错误,但我希望在此行中出现该错误:

contentView.addSubview(self)

因为它正是这么做的,所以添加self作为已经是self子视图的视图的子视图。

答案 2 :(得分:0)

如果我的替代答案太多,请让我尝试解决您现有的问题。代替下面的内容;

Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
contentView.addSubview(self)

尝试;

let nibView = Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
self.addSubView(nibView)