简体   繁体   English

Swift中的惰性变量是否多次计算?

[英]Are lazy vars in Swift computed more than once?

Are lazy vars in Swift computed more than once? Swift中的惰性变量是否多次计算? I was under the impression that they replaced the: 我的印象是,他们取代了:

if (instanceVariable) {
    return instanceVariable;
}

// set up variable that has not been initialized

Paradigm from Objective-C (lazy instantiation). 来自Objective-C的范例(延迟实例化)。

Is that what they do? 那是他们的工作吗? Basically only called once the first time the app asks for the variable, then just returns what was calculated? 基本上只在应用程序第一次要求变量时调用一次,然后才返回计算的结果?

Or does it get called each time like a normal computed property? 还是像普通的计算属性那样每次都调用它?

The reason I ask is because I basically want a computed property in Swift that can access other instance variables. 我问的原因是因为我基本上希望在Swift中获得一个可访问其他实例变量的计算属性。 Say I have a variable called "fullName" and it just concatenates firstName and lastName . 假设我有一个名为“ fullName”的变量,它只是连接firstNamelastName How would I do that in Swift? 我将如何在Swift中做到这一点? It seems like lazy vars are the only way to go, as in normal computed vars (non-lazy) I can't access other instance variables. 似乎惰性变量是唯一的方法,因为在普通的计算变量(非惰性)中,我无法访问其他实例变量。

So basically: 所以基本上:

Do lazy vars in Swift get called more than once? Swift中的懒惰变量是否被多次调用? If so, how do I create a computed variable that can access instance variables? 如果是这样,我如何创建一个可以访问实例变量的计算变量? If not, if I only want a variable to be computed once for performance reasons, how do I do this? 如果不是,如果出于性能原因我只希望一次计算一个变量,该怎么做?

lazy var s are only calculated once, the first time you use them. 第一次使用lazy var只会计算一次。 After that, they're just like a normal variable. 之后,它们就像一个普通变量。

This is easy to test in a playground: 这很容易在操场上测试:

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)
// ???

If you'll want to recalculate it later, use a computed property (with a backing variable, if it's expensive) - just like you did in Objective-C. 如果以后要重新计算,请使用计算属性(如果有昂贵的话,请使用后备变量)-就像在Objective-C中一样。

No, lazy properties are initialized only once. 不,惰性属性仅初始化一次。 If you set a new value, or reset to nil (for optional properties), the lazy initializer is not invoked again. 如果设置新值或重置为nil(用于可选属性),则不会再次调用惰性初始化程序

I think what you need is a computed property - it's not backed by a stored property, so it is not involved in the initialization, and as such you can refer other instance properties. 我认为您需要的是一个计算属性-它没有存储属性的支持,因此它不参与初始化,因此您可以引用其他实例属性。

Why do you say that "normal computed vars (non-lazy) I can't access other instance variables"? 为什么说“普通计算变量(非延迟),我无法访问其他实例变量”?

Answers stating that a lazy var can only be computed once are not true . 答案说一个惰性变量只能被计算一次,这是不正确的 From the documentation at https://docs.swift.org/swift-book/LanguageGuide/Properties.html , the following is stated: https://docs.swift.org/swift-book/LanguageGuide/Properties.html上的文档中,说明了以下内容:

If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once. 如果多个线程同时访问了标记有lazy修饰符的属性,并且该属性尚未初始化,则不能保证该属性仅被初始化一次。

Also, please watch this talk: https://developer.apple.com/videos/play/wwdc2016/720/ . 另外,请观看此演讲: https : //developer.apple.com/videos/play/wwdc2016/720/ At around 17:00, the following screen appears: 在17:00左右出现以下屏幕:

在此处输入图片说明

That talk gives you more insight about multithreading, I recommend you to watch it! 该演讲为您提供了有关多线程的更多见解,我建议您观看!

All the other answers are correct, I would just like to add that Apple warns about lazy variables and concurrency: 所有其他答案都是正确的,我想补充一点, 苹果警告过lazy变量和并发性:

If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once. 如果多个线程同时访问了标记有lazy修饰符的属性,并且该属性尚未初始化,则不能保证该属性仅被初始化一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM