1、前言
在 Swift 编程中,lazy 关键字是一个非常实用的特性,它允许开发者延迟属性的初始化,直到该属性第一次被访问。这一特性在众多场景中都能发挥关键作用,比如初始化那些占用大量内存或计算资源的对象。合理运用 lazy 关键字,能够显著提升应用程序的性能和资源利用率,避免不必要的资源消耗,优化应用的启动时间等。
2、Lazy的底层实现
在 Swift 源码中,lazy 的实现细节可以在 Lazy.h[1] 文件中找到。
创建了两个模版类:LazyValue 用来存储懒加载值,Lazy 用来创建懒加载全局对象。
延迟初始化: LazyValue 在调用 get 方法时会先调用 Value.has_value() 方法检查是否初始化过,如果没有,则调用 Init() 来初始化对象。
一次性赋值: 一旦 lazy 属性被初始化,其值就会被存储起来,后续的访问将直接返回该值,无需重新计算。
3、使用场景
3.1 正确使用场景
3.1.1 延迟加载重量级对象

在上述代码中,databaseConnection 属性使用 lazy 修饰,只有在实际访问它时,才会执行闭包中的代码来创建数据库连接对象,避免了在 DatabaseManager 初始化时就进行耗时的数据库连接操作。
3.1.2 依赖于其他属性的初始化

在这个例子中,只有在访问 fullName 属性时,才会根据已有的 firstName 和 lastName 属性值来计算并初始化 fullName ,保证了属性初始化的时机正确性。在开发过程中,某些属性是通过其他属性计算获取的时候就建议使用lazy修饰,但是需要注意当提供计算值发生变化需要及时更新lazy所修饰的值
3.1.3 条件性资源加载

这里,advancedFeature 属性在条件满足,即需要使用时才会被加载,避免了不必要的资源浪费。在开发过程中,如果使用到的UI标签需要后台给定参数满足条件情况下才渲染,这种情况下lazy修饰该标签,可以节约资源。
3.2、错误的使用场景
3.2.1频繁访问的属性


3.2.2 全局属性且进入即使用
对于全局状态相关的属性,它们应该尽早进行初始化,以便在整个应用的生命周期中都能随时可用。如果使用lazy关键字,会导致全局状态在首次访问时才被初始化,这可能会引发不可预见的延迟或者不一致的行为。比如应用中用于记录全局配置的属性,若使用lazy,在不同模块使用时可能会因为初始化时机不同而出现问题。
4、结论
对于大多数场景,尽量避免使用lazy,除非真的需要延迟初始化。
对于全局状态或频繁访问的属性,最好在应用启动时或首次使用前完成初始化。
通过合理使用lazy关键字,可以提高应用的性能和响应性,同时避免不必要的资源消耗。