我想要一个延迟初始化的属性,如果我将该属性设置为 nil,我可以再次调用其初始化器。
如果我这样定义我的属性:
lazy var object = { /*init code*/ }()
...然后调用该属性,初始化器被触发一次。但是,如果我稍后在我的程序中将 object
设置为 nil,则不会再次调用初始化程序。我如何在 Swift 中做到这一点?
我研究了计算属性,但它们实际上并不存储值,所以每当我调用变量时,计算或初始化总是发生。我只想在属性为 nil 时计算。
最佳答案
惰性属性初始化器负责在第一次以读取模式访问时初始化属性。设置为 nil 对初始化状态没有影响 - 它只是属性存储的有效值。
您可以使用 3 个属性模拟延迟初始化:
- 私有(private)初始化器,作为计算属性实现(或者如果您愿意,也可以作为闭包实现)
- 私有(private)支持属性,存储实际值
- 非私有(private)属性,即您在代码中实际使用的属性
代码如下所示:
class MyClass {
private var _myPropInitializer: Int {
return 5
}
private var _myProp: Int?
var myProp: Int? {
get {
if self._myProp == nil {
self._myProp = self._myPropInitializer
}
return _myProp!
}
set {
_myProp = newValue
}
}
}
- initializer 属性在变量需要初始化时返回一个计算值,即上例中的
5
整数 myProp
是一个可选的整数(能够存储一个nil
):- 在集合中,它将新值存储在
_myProp
属性中 - 获取时,如果
_myProp
为nil
,它会调用初始化程序,将其分配给_myProp
,并返回其值
- 在集合中,它将新值存储在
如果你想重用那个模式,最好把所有东西都放在一个类中:
class Lazy<T> {
private let _initializer: () -> T
private var _value: T?
var value: T? {
get {
if self._value == nil {
self._value = self._initializer()
}
return self._value
}
set {
self._value = newValue
}
}
required init(initializer: () -> T) {
self._initializer = initializer
}
}
注意:struct
不可用,因为不允许在属性 getter 中设置属性,而在类中则可以。
然后你可以像下面这样使用它:
class MyTestClass {
var lazyProp: Lazy<Int>
init() {
self.lazyProp = Lazy( { return 5 } )
}
}
Playground 上的一些测试:
var x = MyTestClass()
x.lazyProp.value // Prints {Some 5}
x.lazyProp.value = nil
x.lazyProp._value // Prints nil
x.lazyProp.value // Prints {Some 5}
缺点是您必须以 x.lazyProp.value
而不是 x.lazyProp
访问实际属性。
关于ios - 通过将属性设置为 nil 在 Swift 中再次触发惰性初始化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25760088/