Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy loading property in Extension (Swift)

Tags:

ios

swift

I know that swift doesn't allow declaring stored property within extension. And by the same token, lazily loaded properties are also prohibited. I know computed property is an alternative, but the task I have should only be executed once.

Is there any hack/alternative/overlooked way to mimic lazy var in extension?

Thanks!

like image 592
Daniel Shin Avatar asked Mar 23 '15 03:03

Daniel Shin


People also ask

How to lazily initialize a property in Swift?

To lazily initialize a property in Swift you add the lazy keyword: Note that lazy properties are always declared with var. The closure is called when the property is accessed which can be after initialization completes.

What are lazy properties in Swift language?

Lazy Properties in Swift Swift language allows you to create several different types of properties, including computed, property observers and even lazy properties. In this article, we will learn how lazy properties can provide performance benefits for time consuming calculations. Implementation

What is a lazy Var in Swift?

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. A lazy property might be lesser known to beginners in Swift but are actually super valuable once you know when and how to use them.

When should you use a computed property in Swift?

This is actually a great example of a situation where you should use a computed property. As you can see, now the BMI index is always correct whether you change the weight / height or not. The original example demonstrates how to use lazy variables in Swift. However, in this case, it makes sense to use a computed property instead.


2 Answers

If you don't need to refer to self you can use a static var:

extension String {
    static var count = 0
    static var laughingOutLoud : String = {
        count++

        return "LOL: \(count)"
    }()
}

String.laughingOutLoud // outputs "LOL: 1"
String.laughingOutLoud // outputs "LOL: 1"
String.laughingOutLoud // outputs "LOL: 1"

(You don't need count in your implementation; that's just there to show it's only executed once.)

like image 54
Aaron Brager Avatar answered Oct 06 '22 23:10

Aaron Brager


you can use computed property, combined with associatedObject. in this way, you can mimic a stored property. so the lazy var simulation will be:

// global var's address used as key
var #PropertyKey# : UInt8 = 0
var #varName# : #type# {
    get {
        if let v = objc_getAssociatedObject(self, & #PropertyKey#) as #type# {
            return v
        }else {
            // the val not exist, init it and set it. then return it

            // this way doesn't support nil option value. 
            // if you need nil option value, you need another associatedObject to indicate this situation.
        }
    }
    set {
        objc_setAssociatedObject(self, & #PropertyKey#, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
    }
}
like image 5
SolaWing Avatar answered Oct 06 '22 22:10

SolaWing