使用 IBOutlets 正确设置 UIView 子类

Properly setup UIView subclass with IBOutlets

背景

我在我的 class MyView 中 class 编辑了 UIView。我创建了附加到子 class 的 IBOutlets。当调用 setup() 方法从 init() 进行一些设置时,我发现插座尚未初始化,因此 nil.
我尝试覆盖有效的 layoutSubviews(),但正如我所读,在将新视图添加为子视图后,每次 都会调用 layoutSubviews() ,因此这似乎不是最佳实践。

我想到了这个解决方案:单独调用 setup() - 不是在 class 中,而是在 ViewController MyViewviewDidLoad() 中是的。这似乎有效,但我认为相当不方便。

代码

这是我的代码的简短摘要:

class MyView: UIView {
    @IBOutlet weak var button: UIButton!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

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

    func setup() {
        if button == nil { print("nil") } //prints "nil"
    }
}

问题

本质上,问题是 在 class 内部我应该调用 setup() 方法。

您的设置需要进入 awakeFromNib 而不是 init

override func awakeFromNib() {
    super.awakeFromNib()

    // Your setup here
    setup()
}

awakeFromNib 在视图从 nib 加载后调用,并且在所有插座等已连接后调用。 init(coder:) 在创建视图后调用,但尚未创建/连接其余视图。

但是,使用 init(frame:) 创建视图意味着 awakeFromNib 不会被调用 (真的很明显 - 这个里面没有 nib案例!)因此您可能还必须在其中放置一些设置代码 - 完全取决于您的用例。