简体   繁体   English

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

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

I want to setup a variable using let so that its not optional, won't change over time and doesn't require messy unwrapping to access each time. 我想使用let设置变量,以便它不是可选的,不会随时间变化,也不需要每次都进行混乱的展开。 I know I can legally set it, but only inside one of the init methods. 我知道我可以合法设置它,但是只能在一种init方法中设置。 The problem is that Swift requires you to override the init(coder aDecoder: NSCoder) initializer. 问题是Swift要求您重写init(coder aDecoder: NSCoder)初始化程序。 However I've never had an app that ever has that initializer called. 但是,我从来没有一个应用程序调用过该初始化程序。 Its always the init(frame: CGRect) initializer that is called. 它始终是被调用的init(frame: CGRect)初始化程序。 So if I didn't have to override init(coder aDecoder: NSCoder) then I'd just do the self.imageView = UIImageView.new() in init(frame: CGRect) and I'd be done, but the compiler complains that its not set in the other init as well. 因此,如果我不必重写init(coder aDecoder: NSCoder)那么只需在init(frame: CGRect)进行self.imageView = UIImageView.new() init(frame: CGRect) ,但是编译器会抱怨它也没有在另一个init中设置。 I tried making a sharedInit() method that is called from both inits, but the compiler won't let me set the imageView from there since it's read only outside of the init methods. 我试图制作一个从两个sharedInit()都调用的sharedInit()方法,但是编译器不允许我从那里设置imageView ,因为它只能在init方法之外读取。 How are you supposed to accomplish this without doing all of your init twice directly in the init methods? 您应该如何在不直接在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
    }

}

Just use a combination of lazy initialization and private 'set' to get: 只需结合使用惰性初始化和私有“设置”即可:

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
}

The 'private set' makes this externally identical to a let ; “私有集”在外部使它与let相同; the lazy lets you initialize the value based on the other state in the SuperCoolView instance. lazy允许您基于SuperCoolView实例中的其他状态来初始化值。

Note that if the initialization of imageView, and others, doesn't depend on state in the instance, then you can avoid the lazy and just do the initialization from the closure. 请注意,如果imageView等的初始化不依赖于实例中的状态,则可以避免lazy而只需从闭包中进行初始化即可。

I found this answer and liked it's approach. 我找到了这个答案,并喜欢它的方法。 It fixed the problem, and is much cleaner IMHO. 它解决了该问题,并且更干净,恕我直言。 By implementing init(coder aDecoder: NSCoder) normally we would be keeping up the appearance that this view can be initialized from a nib/storyboard when it can't. 通常,通过实现init(coder aDecoder: NSCoder)我们可以保持外观可以在无法通过笔尖/故事板初始化的情况下进行。

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

} }

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

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