关于Swift懒加载变量与可选变量实现效果是否等同的技术疑问
嘿,这个问题问得特别好!咱们直接说结论:这两种写法的效果完全不一样,甚至可以说第二个写法是反优化的,下面给你拆解清楚两者的核心差异:
1. 初始化次数完全不同
lazy var的核心特性就是仅在第一次被访问时初始化一次,之后不管你调用多少次buttonPressed,拿到的都是同一个HeavyClass实例:
class MainViewController: UIViewController { lazy var heavyClass = HeavyClass() func buttonPressed () { // 无论点击多少次,这里始终是同一个HeavyClass对象 self.heavyClass.doStuff() } }
而你的第二个写法,每次点击按钮都会创建一个全新的HeavyClass实例,旧的实例会被丢弃(等着ARC回收),不仅白白浪费内存和初始化资源,还会丢失HeavyClass内部的状态(比如如果它有属性记录操作历史,每次点击都会重置):
class MainViewController: UIViewController { var heavyClass : HeavyClass? func buttonPressed () { // 每次点击都new一个新对象,覆盖旧的 self.heavyClass = HeavyClass() self.heavyClass!.doStuff() } }
2. 安全性与可读性差异
lazy var是非可选类型,你永远不需要用!强制解包,完全避免了可选型解包崩溃的风险,代码意图也非常清晰:“这个对象会延迟初始化,且只会存在一个实例”。- 第二个写法用了可选型,不仅每次都要强制解包(万一哪天不小心在初始化前调用,直接崩溃),其他开发者看代码时也会困惑:这个变量是会被多次赋值?还是只初始化一次?可读性差很多。
3. 线程安全的区别
Swift从1.2版本开始,lazy var的初始化就是线程安全的——即使多个线程同时访问,也只会初始化一次,不会出现竞态条件。而第二个写法完全没有线程安全保障,如果多个线程同时点击按钮,可能会创建多个HeavyClass实例,甚至出现不可预期的内存问题。
如果你想让第二个写法接近lazy var的效果?
如果一定要用可选型实现类似延迟初始化的逻辑,你需要先判断实例是否已存在,不存在才创建,比如:
class MainViewController: UIViewController { var heavyClass : HeavyClass? func buttonPressed () { // 先复用已有的实例,没有才创建 let targetClass = self.heavyClass ?? HeavyClass() self.heavyClass = targetClass targetClass.doStuff() } }
但这种写法不仅比lazy var繁琐,还需要自己手动处理线程安全(比如加锁),完全没必要——lazy var已经帮你封装好了所有这些细节。
总结一下:第一种lazy var的写法是正确的延迟初始化方案,能真正达到启动时不占用内存、后续复用实例的优化效果;第二种写法完全达不到这个目的,反而会带来额外的性能开销和风险。
内容的提问来源于stack exchange,提问作者Gizmodo
相关产品推荐
相关产品推荐

