延迟加载属性(Swift)

时间:2023-01-15 23:01:24

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.

我知道swift不允许在扩展中声明存储的属性。同样,也禁止延迟加载属性。我知道计算属性是一种替代方法,但是我的任务应该只执行一次。

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

有什么方法可以在扩展中模仿lazy var吗?

Thanks!

谢谢!

2 个解决方案

#1


4  

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

您可以使用计算属性,并与associatedObject相结合。通过这种方式,您可以模拟存储的属性。因此,懒惰的var模拟将是:

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

#2


7  

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

如果不需要引用self,可以使用静态var:

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

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

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

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

(在实现中不需要计数;那只是为了显示它只执行了一次)

#1


4  

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

您可以使用计算属性,并与associatedObject相结合。通过这种方式,您可以模拟存储的属性。因此,懒惰的var模拟将是:

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

#2


7  

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

如果不需要引用self,可以使用静态var:

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

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

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

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

(在实现中不需要计数;那只是为了显示它只执行了一次)