如何使用共享初始化方法初始化 let 变量?

How can I initialize a let variable using a shared init method?

我想使用 let 设置一个变量,这样它就不是可选的,不会随着时间的推移而改变,也不需要每次都进行混乱的解包访问。我知道我可以合法地设置它,但只能在 init 方法之一中进行。问题是 Swift 要求您重写 init(coder aDecoder: NSCoder) 初始值设定项。但是,我从来没有一个应用程序调用过该初始化程序。它总是调用 init(frame: CGRect) 初始值设定项。因此,如果我不必覆盖 init(coder aDecoder: NSCoder) 那么我只需在 init(frame: CGRect) 中执行 self.imageView = UIImageView.new() 就可以了,但是编译器抱怨它没有在另一个中设置初始化也是如此。我尝试制作一个从两个 init 调用的 sharedInit() 方法,但编译器不允许我从那里设置 imageView,因为它只在 init 方法之外读取。如果不直接在 init 方法中执行所有 init 两次,您应该如何完成此操作?

class SuperCoolView : UIView {

    let imageView: UIImageView

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

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

    func sharedInit() {
        self.imageView = UIImageView.new()
        // Other similar shared init
    }

}

只需结合惰性初始化和私有 'set' 即可得到:

class SuperCoolView : UIView {
  public private(set) lazy var imageView: UIImageView = {
    // In practice, do more here.  Access state in this instance.
    // Or, include more computation.
    UIImageView.new()
  }()

  // inits w/o setting imageView
}

'private set' 使它在外部与 let 相同; lazy 允许您根据 SuperCoolView 实例中的其他状态初始化值。

请注意,如果 imageView 等的初始化不依赖于实例中的状态,那么您可以避免 lazy 并仅从闭包中进行初始化。

我找到了 this answer 并喜欢它的方法。它解决了这个问题,并且更干净恕我直言。通过正常实施 init(coder aDecoder: NSCoder),我们将保持外观,即此视图可以从 nib/storyboard 初始化,但它不能。

class SuperCoolView : UIView {

let imageView: UIImageView

required init(coder aDecoder: NSCoder) {
    fatalError("NSCoding not supported")
}

override init(frame: CGRect) {
    self.imageView = UIImageView.new()
    // Other stuff
    super.init(frame: frame)
}

}