32

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

if (instanceVariable) {
    return instanceVariable;
}

// set up variable that has not been initialized

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

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

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

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

所以基本上:

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

4

4 回答 4

32

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 中所做的那样。

于 2014-10-19T20:23:09.260 回答
7

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

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

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

于 2014-10-19T20:09:58.167 回答
4

说明惰性 var 只能计算一次的答案是不正确的。从https://docs.swift.org/swift-book/LanguageGuide/Properties.html的文档中,声明如下:

如果一个带有惰性修饰符的属性同时被多个线程访问,并且该属性还没有被初始化,则不能保证该属性只会被初始化一次。

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

在此处输入图像描述

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

于 2019-02-16T18:34:34.607 回答
4

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

如果一个带有惰性修饰符的属性同时被多个线程访问,并且该属性还没有被初始化,则不能保证该属性只会被初始化一次。

于 2019-01-23T17:44:02.243 回答