-
1.單例是一個在 Cocoa 中很常用的模式了。對于一些希望能在全局方便訪問的實例帜平,或者在 app 的生命周期中只應(yīng)該存在一個的對象橘霎,我們一般都會使用單例來存儲和訪問腌且。在 Objective-C 中單例的公認的寫法類似下面這樣:
@implementation TestViewController + (id)sharedManager { static TestViewController *staticInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ staticInstance = [[self alloc] init]; }); return staticInstance; } @end
使用 GCD 中的 dispatch_once_t 可以保證里面的代碼只被調(diào)用一次,以此保證單例在線程上的安全。
-
2.因為在 Swift 中可以無縫直接使用 GCD航背,所以我們可以很方便地把類似方式的單例用 Swift 進行改寫:
class TestViewController: UIViewController { class var sharedManager : TestViewController { struct Static { static var onceToken : dispatch_once_t = 0 static var staticInstance : TestViewController? = nil } dispatch_once(&Static.onceToken) { Static.staticInstance = TestViewController() } return Static.staticInstance! } }
-
3.因為 Swift 1.2 之前并不支持存儲類型的類屬性喉悴,所以我們需要使用一個 struct 來存儲類型變量。
這樣的寫法當然沒什么問題玖媚,但是在 Swift 里我們其實有一個更簡單的保證線程安全的方式箕肃,那就是 let。把上面的寫法簡化一下今魔,可以變成:class TestViewController: UIViewController { class var sharedManager : TestViewController { struct Static { static let sharedInstance : TestViewController = TestViewController() } return Static.sharedInstance } }
- 還有另一種更受大家歡迎突雪,并被認為是 Swift 1.2 之前的最佳實踐的做法。由于 Swift 1.2 之前 class 不支持存儲式的 property涡贱,我們想要使用一個只存在一份的屬性時咏删,就只能將其定義在全局的 scope 中。值得慶幸的是问词,在 Swift 中是有訪問級別的控制的督函,我們可以在變量定義前面加上 private 關(guān)鍵字,使這個變量只在當前文件中可以被訪問激挪。這樣我們就可以寫出一個沒有嵌套的辰狡,語法上也更簡單好看的單例了:
private let sharedInstance = TestViewController()
class TestViewController: UIViewController {
class var sharedManager : TestViewController {
return sharedInstance
}
}
- swift3.0以后我們普遍使用“果沒有特別的需求,我們推薦使用下面這樣的方式來寫一個單例:
class TestViewController: UIViewController {
private static let sharedInstance = TestViewController()
class var sharedManager : TestViewController {
return sharedInstance
}
}