Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are lazy vars in Swift computed more than once?

Are lazy vars in Swift computed more than once? 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).

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. Say I have a variable called "fullName" and it just concatenates firstName and lastName. How would I do that in 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? 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?

like image 482
Doug Smith Avatar asked Oct 19 '14 20:10

Doug Smith


People also ask

How does Swift define lazy VAR?

A lazy var is a property whose initial value is not calculated until the first time it's called. It's part of a family of properties in which we have constant properties, computed properties, and mutable properties.

How is lazy stored property useful in Swift?

Lazy properties are useful when the initial value for a property is dependent on outside factors whose values are not known until after an instance's initialization is complete.

Is lazy var thread safe Swift?

Another problem is that lazy var is not thread-safe which means the closure can get executed multiple times due to accesses from different threads.

What is lazy and weak in Swift?

The error message is completely useless at explaining what is going on, but essentially lazy and weak are at odds with each other: lazy tells Swift that you don't want your variable created until the first time you access it, but once it is created, you want to keep it indefinitely for future reference, while.


4 Answers

lazy vars are only calculated once, the first time you use them. 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.

like image 187
Aaron Brager Avatar answered Oct 05 '22 05:10

Aaron Brager


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.

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"?

like image 40
Antonio Avatar answered Oct 05 '22 05:10

Antonio


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:

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.

Also, please watch this talk: https://developer.apple.com/videos/play/wwdc2016/720/. At around 17:00, the following screen appears:

enter image description here

That talk gives you more insight about multithreading, I recommend you to watch it!

like image 26
J. Doe Avatar answered Oct 05 '22 04:10

J. Doe


All the other answers are correct, I would just like to add that Apple warns about lazy variables and concurrency:

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.

like image 41
Balázs Vincze Avatar answered Oct 05 '22 04:10

Balázs Vincze