为什么从 XIB 以编程方式创建 UIView 后我的 UILabel 为零? (附代码)

Why is my UILabel nil after creating UIView programmatically from XIB? (code attached)

问题:为什么在从 XIB 以编程方式创建 UIView 后,初始化中的 UILabel 为 nil(附加代码)? (参考下面的代码)那是行label1.text = "TBC - It was updated" throws an error

背景:我想以编程方式创建多个自定义视图,在本例中为多个 GCDateView。我想使用 XIB 文件来布局自定义视图以及关联的 class 以编程方式完成自定义,因此这里我有一个 GCDateView.swift 和一个 GCDateView.xib 文件。

旁白:作为第二个旁白问题,我注意到我在 GCDateView 中从 xib 文件创建的视图不能直接分配为主视图(例如在初始化结束我不能说 self = gcDateViewView)。也许我需要一个单独的问题。

来自 parent controller/view:

let dv = GCDateView()

GCDateView:

import UIKit

class GCDateView : UIView {

    @IBOutlet weak var label1: UILabel!

    func commonInit() {
        // Programmtically use XIB file
        if self.subviews.count == 0 {
            let bundle = Bundle(for: type(of: self))
            let nib = UINib(nibName: "GCDateView", bundle: bundle)
            let gcDateViewView : UIView = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
            gcDateViewView.frame = self.bounds
            gcDateViewView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            addSubview(gcDateViewView)
        }
        **label1.text = "TBC - It was updated"  // ** ERROR: label1 was Nil ****
    }

    override init(frame: CGRect) {
        NSLog("GCDateView: Init frame")
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        NSLog("GCDateView: Init decoder")
        super.init(coder: aDecoder)
        commonInit()
    }

}

IBOutlet 个实例未在 init?(coder aDecoder: NSCoder) 中初始化。
这个过程是在单独的步骤中完成的。

有方法 awakeFromNib 可以保证所有 IBOutlet 个实例都已初始化:

override func awakeFromNib() {
    super.awakeFromNib()
    label1.text = "TBC - It was updated" // Won't crash.
}

为了解决你的第二个问题(即避免添加另一个自我类型的实例作为自我子视图)我建议创建 class 方法,该方法将通过从 xib 加载它来创建 GCDateView 的新实例。
这是更新的代码:

import UIKit

class GCDateView : UIView {

    @IBOutlet weak var label1: UILabel!

    class func loadFromXIB() -> GCDateView {
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: "GCDateView", bundle: bundle)
        let gcDateView = nib.instantiate(withOwner: self, options: nil)[0] as! GCDateView
        gcDateView.frame = self.bounds
        gcDateView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        gcDateView.label1.text = "TBC - It was updated"

        return gcDateView
    }
}

用法:

let dateView = GCDateView.loadFromXIB()