You need to enable JavaScript to run this app. Swift 属性声明:类初始化或首个执行块中lazy var与let的使用区别
优惠活动
大模型
产品
解决方案
定价
更多

Swift 属性声明:类初始化或首个执行块中lazy var与let的使用区别

lazy var 与 let 声明属性在指定开发场景下的核心区别

结合给出的两个示例,两者在初始化时机、内存开销、生命周期适配、可变性约束上的差异非常明确:

  • 属性初始化触发时机完全不同
    let 修饰的存储属性,会在实例创建完成的阶段(也就是 UIViewController 的 init 流程执行结束时)就立刻完成初始化。哪怕整个控制器生命周期里你从来没访问过这个 label,对应的 UILabel 实例在控制器刚被创建时就已经生成。
    lazy var 修饰的属性,只有第一次被代码访问时才会真正执行初始化逻辑,且初始化逻辑只会执行一次。对应你的示例,UILabel() 的创建代码只有走到 viewDidLoad 里的 label.text = "hey" 这行、第一次触达属性访问时才会执行,之后的访问和普通的可变属性没有差异。
  • UIKit 生命周期的适配性差异
    控制器的 init 阶段和后续的 viewDidLoad 阶段是完全独立的两个流程:init 执行时控制器的根视图还没被加载,屏幕尺寸、安全区、导航栏状态这些视图相关的信息都还没确定。
    用 let 在控制器初始化阶段就创建视图类控件,本质就是生成了一个完全脱离当前视图流程的离屏对象,不仅没法拿到正确的布局上下文,还可能触发系统隐式的视图布局逻辑带来不必要的性能损耗。
    而 lazy var 把初始化时机推迟到第一次访问(也就是你在 viewDidLoad 里使用属性的节点),刚好匹配视图加载完成后的流程节奏,完全符合 UIKit 的生命周期设计逻辑。
  • 内存占用的差异
    只要控制器实例存在,let 声明的属性就会一直占用对应的内存——哪怕这个属性从来没被使用过、也没被加到视图层级里。
    如果代码从头到尾没有访问过这个 lazy var 属性,它的初始化逻辑永远不会执行,对应的内存也永远不会被分配,能避免大量无效的内存开销。
  • 可变性约束的差异
    let 修饰的属性,仅仅是引用地址不可变:你不能把 label 重新指向另一个新的 UILabel 实例,但 label 自身的属性(比如 text、frame)完全可以正常修改。
    lazy var 因为是 var 修饰的,不仅可以修改属性内部的值,还可以随时把整个 label 引用替换为其他实例,灵活性更高,但对引用的不可变约束更弱。

补充一个常见误区:很多开发者会误以为 let 声明控件更早初始化会更可靠,实际在 iOS 控制器的开发场景中,过早在 init 阶段初始化视图控件,往往是无意义的性能浪费,也是很多隐蔽的内存泄漏问题的来源。

内容的提问来源于stack exchange,提问作者Mellao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 16:36:11