简体   繁体   English

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

[英]Custom UIView is blank when instantiated from a XIB in Swift 4

I have a custom view that I am trying to load from a custom XIB, but the view appears to be blank when loaded, even thought it has the correct sizes when debugged. 我有一个试图从自定义XIB加载的自定义视图,但是加载后该视图似乎是空白的,甚至认为调试时它的大小正确。

My debug statements show that the frame has the correct sizes: 我的调试语句显示框架具有正确的大小:

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

This is my custom VC that I am using to call my Custom View 这是我用来调用“自定义视图”的自定义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)
    }
}

There is a XIB that has the files owner as MyCustomView and all the outlets are hooked up correctly. 有一个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
    }
}

Does anyone see what I have done wrong when trying to load the view 有人在尝试加载视图时是否看到我做错了什么

I'm going to post an alternative to what you've done, using an extension. 我将使用扩展程序发布您所做的替代方案。

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
    }
}

*Note that I am using PureLayout for convenient autolayout management, you could just apply the constraints manually yourself though if you aren't using PureLayout. *请注意,我正在使用PureLayout进行方便的自动布局管理,即使您不使用PureLayout,也可以自己手动应用约束。

Using the above all you have to do is call the below from your init; 使用以上所有操作,您只需从init调用以下内容;

fromNib()

*Final note. *最后的笔记。 The custom view name must match the nib name, otherwise you must pass the nib name in to you fromNib function. 自定义视图名称必须与笔尖名称匹配,否则,您必须从nib函数将笔尖名称传递给您。

You now have something much more reusable. 您现在有了更多可重用的东西。

I couldn't get this to run copy/pasting the code. 我无法获取此代码来运行复制/粘贴代码。 Maybe there's some setup missing, but I'm having a hard time understanding how it's supposed to work. 也许缺少一些设置,但是我很难理解它应该如何工作。 The original code in the question crashes on this line: 问题中的原始代码在此行崩溃:

contentView.addSubview(self)

because when you have IBOutlets , they will always be nil if you initialize it using MyCustomView(frame: self.view.frame) . 因为当您拥有IBOutlets ,如果使用MyCustomView(frame: self.view.frame)对其进行初始化,则它们将始终为nil It has to call the initWithCoder function. 它必须调用initWithCoder函数。

There's a lot going on here, but this is how I would do it: 这里有很多事情,但这就是我要做的:

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!

}

I'm assuming that the top-level object in the nib is of class MyCustomView , which is going to lead to a lot of weird things. 我假设笔尖中的顶级对象是MyCustomView类,这将导致很多奇怪的事情。 loadNibNamed will call init?(coder aDecoder: NSCoder) , so ideally you'd just be calling that from your view controller in the first place, instead of from the custom view object. loadNibNamed将调用init?(coder aDecoder: NSCoder) ,因此理想情况下,您首先只是从视图控制器而不是自定义视图对象调用它。

With regards to the "can't add self as subview" error, I did not see that error while running, but I would expect it from this line: 关于“无法将自己添加为子视图”错误,我在运行时没有看到该错误,但我希望从此行可以看到它:

contentView.addSubview(self)

since that's exactly what it does, add self as a subview of a view that's already a subview of self . 因为这正是它,加入self因为这是已经是一个子视图视图的子视图self

If my alternative answer is too much, let me try solve your existing issue. 如果我的替代答案太多,请让我尝试解决您现有的问题。 Instead of the below; 代替下面的内容;

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

Try; 尝试;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM