我想要一个lazily-initialized属性,如果我将属性设置为nil,我可以再次调用它。
如果我以这种方式定义我的属性:
lazy var object = { /*init code*/ }()
...然后调用属性,初始化程序被触发一次。但是,如果我稍后在程序中将object
设置为nil,则不会再次调用初始值设定项。我怎么能在Swift中做到这一点?
我查看了计算属性,但它们实际上并不存储值,因此每当我调用变量时,总会发生计算或初始化。我只想在属性为零时计算。
答案 0 :(得分:16)
lazy属性初始化程序负责在读取模式下第一次访问属性时初始化该属性。设置为nil对初始化状态没有影响 - 它只是属性存储的有效值。
您可以使用3个属性模仿延迟初始化:
代码如下所示:
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
}
}
}
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 } )
}
}
在操场上进行一些测试:
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
访问实际属性。
答案 1 :(得分:2)
这是我在您的对象只能是nil
或计算值时使用的惰性模式。它只需要2个属性:
var todayPredicate: NSPredicate! {
set {
guard newValue == nil else {return} // could throw here if required
self._todayPredicateLazyBacker = nil
}
get {
guard self._todayPredicateLazyBacker == nil else {return self. _todayPredicateLazyBacker}
// construct your today predicate
let predicate = ...
self._todayPredicateLazyBacker = predicate
return self._todayPredicateLazyBacker
}
}
private var _todayPredicateLazyBacker: NSPredicate?
todayPredicate
在第一次读取时(懒惰)只构造一次。
那你为什么要把todayPredicate
设为零呢?在这个例子中,您可能正在观察当天的变化,因为todayPredicate
必须始终代表今天。在您的观察者代码中,您只需执行此操作,例如......
self.todayPredicate = nil
self.loadEvents()