在 iOS/macOS 開發中,某些屬性的初始化開銷極大(如解析大型 JSON、創建複雜視圖層級、建立數據庫連接),若在對象構造時一律初始化,會嚴重拖慢啟動速度與內存佔用。Swift 的 延遲存儲屬性 完美解決此痛點:首次訪問時才計算初始值。
class DataLoader {
// 必須用 var,不能用 let
lazy var expensiveResource: HeavyResource = {
print("🔧 正在初始化昂貴資源...")
return HeavyResource()
}()
}
關鍵點:
lazy 修飾var(常量 let 需在構造完成前確定值)() 表示立即執行閉包並賦值結果dispatch_once 模式)class ImageCache {
lazy var cache: NSCache = {
let c = NSCache()
c.countLimit = 100
c.totalCostLimit = 50 * 1024 * 1024 // 50MB
return c
}()
}
class ProfileVC: UIViewController {
lazy var headerView: ProfileHeaderView = {
let v = ProfileHeaderView()
v.delegate = self
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(headerView) // 首次訪問觸發創建
}
}
self 的閉包)class NetworkManager {
lazy var session: URLSession = {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30
return URLSession(configuration: config, delegate: self, delegateQueue: nil)
}()
}
class Bird {
let name: String
init(name: String) {
self.name = name
print("🐣 Bird \(name) 初始化")
Thread.sleep(forTimeInterval: 2) // 模擬耗時操作
}
}
class Ostrich {
let name = "鴕鳥"
var bird = Bird(name: "鳥類") // 非 lazy,構造時立即初始化
}
class LazyOstrich {
let name = "鴕鳥"
lazy var bird = Bird(name: "鳥類") // lazy,首次訪問才初始化
}
// 測試
print("--- 非 Lazy ---")
let o1 = Ostrich() // 這裡會卡 2 秒
print("Ostrich 創建完成") // 2 秒後才打印
print("\n--- Lazy ---")
let o2 = LazyOstrich() // 瞬間完成
print("LazyOstrich 創建完成")
print("訪問 bird 屬性...")
_ = o2.bird // 這裡卡 2 秒
print("Bird 初始化完成")
輸出對比:
--- 非 Lazy ---
🐣 Bird 鳥類 初始化
(等待 2 秒...)
Ostrich 創建完成
--- Lazy ---
LazyOstrich 創建完成
訪問 bird 屬性...
🐣 Bird 鳥類 初始化
(等待 2 秒...)
Bird 初始化完成
mutating。self 時使用 [weak self] 或 [unowned self]。lazy var resource: Resource = { ... }() 配合 NSLock 或改用 let resource = { ... }() 在構造器中初始化。| 特性 | lazy 存儲屬性 | 計算屬性 |
|---|---|---|
| 存儲開銷 | 首次訪問後佔用內存 | 不佔用額外內存 |
| 計算頻率 | 僅首次計算,後續直接讀取 | 每次訪問皆計算 |
| 適用場景 | 昂貴、固定、可緩存的結果 | 輕量、動態、依賴外部狀態 |
lazy 是 Swift 為「按需初始化」提供的原生語法支持,能顯著優化啟動性能與內存佔用。實戰中,凡涉及耗時構造、非必需即用、依賴 self 上下文的屬性,優先考慮 lazy。但記住:它不是銀彈,線程安全與循環引用仍需開發者把控。
下一期將深入講解計算屬性與屬性觀察器,構建響應式數據流的基石,敬請關注。