【问题标题】:How can I initialize a let variable using a shared init method?如何使用共享的 init 方法初始化 let 变量?
【发布时间】:2015-03-18 21:13:15
【问题描述】:

我想使用let 设置一个变量,这样它就不是可选的,不会随着时间的推移而改变,也不需要每次都进行混乱的解包访问。我知道我可以合法地设置它,但只能在 init 方法之一内。问题是 Swift 要求你重写 init(coder aDecoder: NSCoder) 初始化器。但是,我从未有过调用该初始化程序的应用程序。它始终是被调用的 init(frame: CGRect) 初始化程序。因此,如果我不必覆盖init(coder aDecoder: NSCoder),那么我只需在init(frame: CGRect) 中执行self.imageView = UIImageView.new() 就可以了,但是编译器抱怨它也没有在另一个init 中设置。我尝试创建一个从两个 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
    }

}

【问题讨论】:

标签: ios swift


【解决方案1】:

只需结合使用惰性初始化和私有'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
}

“私有集”使得它在外部与let 相同; lazy 允许您根据 SuperCoolView 实例中的其他状态初始化值。

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

【讨论】:

  • 为什么不直接使用let imageView = UIImageView()?还是我链接到的答案中基于闭包的let 初始化?
  • 我更新了。我们的更新越过了。是的,如果赋值不依赖于复杂的计算或SuperCoolView 中的状态,那么你可以直接赋值。
  • 我不喜欢在属性声明中使用闭包。这使得以后阅读代码变得更加复杂。我更喜欢 swift 文件的顶部只是具有尽可能少的实现细节的公共方法/属性。为此,我真的很想念头文件。
  • 所以你更喜欢“命名闭包”(如sharedInit)而不是“匿名闭包”?你的意见会改变蚂蚱! :-)
  • 不,我只是更喜欢将 sharedInit 之类的东西“隐藏”在类的实现细节中,而不是与公共属性声明绑定。
【解决方案2】:

我找到了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)
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-22
    • 2020-03-27
    • 2021-10-19
    • 1970-01-01
    • 2020-01-24
    • 2016-03-08
    • 1970-01-01
    • 2017-01-23
    相关资源
    最近更新 更多