扩展中的延迟加载属性(Swift)

Posted

技术标签:

【中文标题】扩展中的延迟加载属性(Swift)【英文标题】:Lazy loading property in Extension (Swift) 【发布时间】:2015-03-23 03:58:32 【问题描述】:

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

在扩展中是否有任何 hack/替代/被忽略的方法来模仿惰性 var?

谢谢!

【问题讨论】:

最好的做法可能是使用您将创建的变量的返回类型为函数 【参考方案1】:

如果您不需要参考self,您可以使用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"

(您的实现中不需要count;这只是为了表明它只执行一次。)

【讨论】:

无论我创建多少个实例,静态变量laughingOutOut 占用的内存都是一个单独的字符串来保存LOL: \(count)。这就是静态工作。我说的对吗?【参考方案2】:

你可以使用计算属性,结合关联对象。通过这种方式,您可以模仿存储的属性。所以惰性 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))
    

【讨论】:

感谢您的回答。有必要使用这种方法吗?如果我只检查#varname# 是否不为零,它会不会给出相同的结果?类似var hi:String = get if let hi = hi return hi else // init hi 。谢谢! 你需要一个地方来存储财产的价值。计算属性只是封装了 getter 和 setter 方法。它没有存储变量的地方。和 associatedObject 提供了这样一个地方。 associatedObject 还将确保对象在不需要时得到释放。就像一个真正的存储属性。如果你在 getter 方法中使用计算属性,我认为这将是一个递归循环,并且会用完堆栈。

以上是关于扩展中的延迟加载属性(Swift)的主要内容,如果未能解决你的问题,请参考以下文章

hibernate 延迟加载

C#中的延迟加载

延迟显示 UIMapView 直到地图在 Swift 中完全加载

Swift Firebase 加载记录延迟很长

JavaScript 中的延迟加载属性模式

实现对象属性的lazy-loading(延迟加载)