我刚收到same problem。
正如 GoZoner 所说,将变量标记为可选将起作用。这不是一种非常优雅的方式,因为您每次想要访问它时都必须解包该值。
我将向 Apple 提交增强请求,也许我们可以获得类似“beforeInit”的方法,该方法在每次初始化之前调用,我们可以在其中分配变量,因此我们不必使用可选变量。
在那之前,我将把所有的赋值放到一个 commonInit 方法中,该方法从专用的初始化程序中调用。例如:
class GradientView: UIView {
var gradientLayer: CAGradientLayer? // marked as optional, so it does not have to be assigned before super.init
func commonInit() {
gradientLayer = CAGradientLayer()
gradientLayer!.frame = self.bounds
// more setup
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
commonInit()
}
init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer!.frame = self.bounds // unwrap explicitly because the var is marked optional
}
}
感谢 David,我再次查看了这本书,我发现了一些可能对我们的重复数据删除工作有所帮助的内容,而无需使用可选的变量 hack。可以使用闭包来初始化变量。
使用闭包或函数设置默认属性值
如果存储属性的默认值需要一些自定义或设置,您可以使用闭包或全局函数为该属性提供自定义默认值。每当初始化属性所属类型的新实例时,就会调用闭包或函数,并将其返回值分配为属性的默认值。这些类型的闭包或函数通常会创建一个与属性相同类型的临时值,修改该值以表示所需的初始状态,然后返回该临时值以用作属性的默认值。
以下是如何使用闭包提供默认属性值的概要:
class SomeClass {
let someProperty: SomeType = {
// create a default value for someProperty inside this closure
// someValue must be of the same type as SomeType
return someValue
}()
}
请注意,闭包的结尾大括号后面是一对空括号。这告诉 Swift 立即执行闭包。如果你省略这些括号,你试图将闭包本身分配给属性,而不是闭包的返回值。
注意
如果您使用闭包来初始化属性,请记住实例的其余部分在执行闭包时尚未初始化。这意味着您不能从闭包中访问任何其他属性值,即使这些属性具有默认值。您也不能使用隐式 self 属性,或调用任何实例的方法。
摘自:Apple Inc.“Swift 编程语言”。电子书。 https://itun.es/de/jEUH0.l
这是我从现在开始使用的方式,因为它不会规避不允许在变量上使用 nil 的有用特性。对于我的示例,它看起来像这样:
class GradientView: UIView {
var gradientLayer: CAGradientLayer = {
return CAGradientLayer()
}()
func commonInit() {
gradientLayer.frame = self.bounds
/* more setup */
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
commonInit()
}
init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
}