swift 中的 lazy

Inlight發表於2017-12-25

概念

  • 延遲載入是初始化很常用的效能優化方式,尤其是在一些物件的屬性十分複雜的時候,預設全部初始化會耗費不少時間,影響效能。還有一些特定環境下才使用的物件,更是浪費資源。所以有些時候我們並不會立刻用到一個物件或者一個物件的所有屬性,使用延遲載入可以提升效能。
  • 所謂延遲載入就是在第一次訪問某個屬性時,要判斷這個屬性是否已經被初始化,如果已經初始化則直接返回,若沒有初始化則進行初始化。這樣可以把這個屬性延遲初始化,把它和包含它的物件的初始化分隔開,來達到提升效能的目的。

使用

swift 中我們在變數屬性前加 lazy 關鍵字來指定延遲載入。

OC 中可能是這樣的:

@property (copy, nonatomic) NSString *name;

- (NSString *)name {
    if (!_name) {
        _name = @"Inlight";
    }
    return _name;
}
複製程式碼

swift 中我們在使用 lazy 修飾屬性時,必須宣告屬性是變數。而且我們需要顯示的指定屬性的型別。對該屬性進行一個賦值語句用來首次訪問時使用。

swift 使用方式:

    lazy var name: String = "Inlight"
    
    lazy var planNameLabel: UILabel = {
        let label = UILabel()
        label.text = "yo yo yo kongfu!"
        return label
    }()
複製程式碼

擴充

lazy 還可以配合 map filter 這類接受閉包執行的方法一起,使整個行為變成延遲進行的。

    let numbers = 1...5
    let doubleNumbers = numbers.map { (i: Int) -> Int in
        print("numbers\(i)")
        return i * 2
    }

    for i in doubleNumbers {
        print("doubleNumbers\(i)")
    }
複製程式碼

列印結果:

numbers1
numbers2
numbers3
numbers4
numbers5
doubleNumbers2
doubleNumbers4
doubleNumbers6
doubleNumbers8
doubleNumbers10
複製程式碼

使用 lazy 後得到延遲執行版本的容器

    let numbers = 1...5
    let doubleNumbers = numbers.lazy.map { (i: Int) -> Int in
        print("numbers\(i)")
        return i * 2
    }

    for i in doubleNumbers {
        print("doubleNumbers\(i)")
    }
複製程式碼

列印結果:

numbers1
doubleNumbers2
numbers2
doubleNumbers4
numbers3
doubleNumbers6
numbers4
doubleNumbers8
numbers5
doubleNumbers10
複製程式碼

對於一些不需要完全執行或者提前退出的情況,使用 lazy 進行效能優化更加有效。

相關文章