【问题标题】:Are lazy vars in Swift computed more than once?Swift 中的惰性变量是否计算不止一次?
【发布时间】:2017-03-04 06:51:19
【问题描述】:

Swift 中的惰性变量是否计算了多次?我的印象是他们取代了:

if (instanceVariable) {
    return instanceVariable;
}

// set up variable that has not been initialized

Objective-C 的范式(惰性实例化)。

他们就是这样做的吗?基本上只在应用第一次请求变量时调用一次,然后只返回计算的内容?

还是像普通的计算属性一样每次都调用它?

我问的原因是因为我基本上想要一个 Swift 中的计算属性,它可以访问其他实例变量。假设我有一个名为“fullName”的变量,它只是连接firstNamelastName。我将如何在 Swift 中做到这一点?似乎惰性变量是唯一的方法,因为在普通计算变量(非惰性)中我无法访问其他实例变量。

所以基本上:

Swift 中的惰性变量会被多次调用吗?如果是这样,我如何创建一个可以访问实例变量的计算变量?如果不是,如果出于性能原因我只想计算一次变量,我该怎么做?

【问题讨论】:

    标签: swift lazy-initialization computed-properties


    【解决方案1】:

    lazy vars 只计算一次,第一次使用它们。之后,它们就像一个普通的变量。

    这很容易在操场上进行测试:

    class LazyExample {
        var firstName = "John"
        var lastName = "Smith"
        lazy var lazyFullName : String = {
            [unowned self] in
            return "\(self.firstName) \(self.lastName)"
        }()
    }
    
    let lazyInstance = LazyExample()
    
    println(lazyInstance.lazyFullName)
    // John Smith
    
    lazyInstance.firstName = "Jane"
    
    println(lazyInstance.lazyFullName)
    // John Smith
    
    lazyInstance.lazyFullName = "???"
    
    println(lazyInstance.lazyFullName)
    // ???
    

    如果您想稍后重新计算它,请使用计算属性(如果它很昂贵,请使用支持变量) - 就像您在 Objective-C 中所做的那样。

    【讨论】:

    • 您的代码没有问题...但它可能具有误导性,即如果您将更改 firstName 更改为“Jane”在访问之前 lazyFullName 然后它会打印“简·史密斯”
    【解决方案2】:

    不,惰性属性只初始化一次。如果您设置一个新值,或重置为 nil(对于可选属性),惰性 initializer不会再次调用。

    我认为您需要的是计算属性 - 它不受存储属性的支持,因此它不参与初始化,因此您可以引用其他实例属性。

    为什么说“普通计算变量(非惰性)我无法访问其他实例变量”?

    【讨论】:

    • 1.你是什​​么意思计算属性不受存储属性的支持? fullName 不是由 firstName、lastName 支持吗? 2. 除了懒惰被初始化一次之外,两者之间的主要区别是:对于懒惰,如果您 set 则您只需设置它...但是对于 computedLazyFullName 如果您设置它,那么您需要一些机制来正确更新 stored firstName, lastName 属性吗?
    【解决方案3】:

    所有其他答案都是正确的,我想补充一点 Apple 警告lazy 变量和并发:

    如果一个用惰性修饰符标记的属性被多个访问 同时线程和属性尚未初始化, 不能保证该属性只会被初始化一次。

    【讨论】:

      【解决方案4】:

      说明惰性变量只能在不正确时计算的答案。在https://docs.swift.org/swift-book/LanguageGuide/Properties.html 的文档中,声明如下:

      如果一个用惰性修饰符标记的属性被多个访问 同时线程并且该属性尚未初始化, 不能保证该属性只会被初始化一次。

      另外,请观看此演讲:https://developer.apple.com/videos/play/wwdc2016/720/。 17:00左右,出现如下画面:

      该演讲让您对多线程有更多的了解,我建议您观看!

      【讨论】:

        猜你喜欢
        • 2015-01-19
        • 2014-09-22
        • 2018-06-11
        • 1970-01-01
        • 2012-06-17
        • 2016-07-16
        • 2020-06-11
        • 2014-12-28
        相关资源
        最近更新 更多