ios - 通过将属性设置为 nil 在 Swift 中再次触发惰性初始化器

标签 ios iphone ipad cocoa-touch swift

我想要一个延迟初始化的属性,如果我将该属性设置为 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 属性中
    • 获取时,如果 _myPropnil,它会调用初始化程序,将其分配给 _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/

相关文章:

objective-c - 苹果支持GDataXML吗

iphone - 设置包中的只读字符串

iphone - 如何在 MFMailComposeViewController 上向正文添加换行

iphone - 如何监控我的应用程序消耗了多少内存?

ios - Metal - 优化内存访问

ios - 无法在 swift iOS 中将项目添加到 NSMutableDictionary

iphone - 如何在 main.h 中设置 iPhone 应用程序语言和区域覆盖设置值

iphone - 公历到希伯来语

java - 修复 Zxing (Obj-C) 中的 Aztec 解码器以返回原始 ByteArray

ios - EXC_BREAKPOINT 代码和子代码的含义是什么?