Swift的惰性初始化方法

weixin_34321977發表於2015-09-15

一直喜歡使用Objective C的惰性初始化, 這樣的程式碼結構會非常清晰和易維護.

@property (nonatomic, strong) NSMutableArray *players;
- (NSMutableArray *)players {
    if (!_players) {
        _players = [[NSMutableArray alloc] init];
    }
    return _players;
} 

當你程式碼裡面呼叫NSArray *xx = self.players時候就會點用這個getter的方法.

使用Swift之後, 我第一個想法就是使用get 和 set 方法去實現惰性初始化, 想法很傻很天真. 下面的程式碼肯定會Crash.

Swift不允許 Objective C的下劃線訪問實體變數. 也就是說你只能用self.xxx這樣去訪問變數. 這樣下面的程式碼在self.locationButton就無限的自己呼叫自己.

 var locationButton: UIButton! {
        get {
             if self.locationButton == nil {
                var button = UIButton()
                return button
            }
            return self.locationButton    
        }
    }
    

優雅的實現: 惰性初始化

實現方式:1

Swift提供了一個lazy的修飾詞, 使用格式 lazy var variable: Class = { //初始化方法 return }()這樣就會完成惰性初始化. 不需要再像Objective C一樣去判斷實體變數是否為nil.

lazy var mapView: MAMapView! = {
        var mapView = MAMapView(frame: CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)))
        mapView.delegate = self
        mapView.compassOrigin.y = 24
        mapView.scaleOrigin.y = 24
        
        mapView.showsUserLocation = true
        return mapView
    }()
實現方式:2

使用func 去完成惰性初始化, 通過函式的返回值來確定初始化, 這樣你需要手動寫一個func去做, 個人不太喜歡這樣的方式, 不過也是一種實現方式.

lazy var players: [String] = self.initialPlayers()

func initialPlayers() -> [String] {
    var players = ["John Doe"]
    return players
}

最後補充一下, get和set的方法屬於計算屬性, 不能拿來作為惰性初始化.
Swift 程式語言中把這些理論統一用屬性來實現。Swift 中的屬性沒有對應的例項變數,屬性的後端儲存也無法直接訪問。這就避免了不同場景下訪問方式的困擾,同時也將屬性的定義簡化成一個語句。 一個型別中屬性的全部資訊——包括命名、型別和記憶體管理特徵——都在唯一一個地方(型別定義中)定義。
Swift 屬性介紹

參考文獻:

Swift 惰性載入 , Swift lazy

相關文章