+ (instancetype)sharedInstance {
static dispatch_once_t once;
static id instance = nil;
dispatch_once(&once) { instance = [[self alloc] init]; };
return instance;
}
class Singleton1 {
static let shared = Singleton1() // 唯一實例,lazy + thread-safe
private init() {} // 防止外部初始化
}
// 使用
let s1 = Singleton1.shared
優點:語法極簡、編譯器保證線程安全、延遲初始化。
class Singleton2 {
static var shared: Singleton2 {
struct Holder {
static let instance = Singleton2()
}
return Holder.instance
}
private init() {}
}
原理:結構體靜態常量首次存取時初始化,Swift 保證原子性。
class Singleton3 {
static var shared: Singleton3 {
var instance: Singleton3?
var token: Int = 0
// Swift 3+ 已移除 dispatch_once,改用上述版本一/二
// 此處僅示意 Objective-C 思維對應
return instance!
}
private init() {}
}
注意:Swift 3 起
dispatch_once已棄用,官方推薦靜態常量或巢狀型別方式。
| 特性 | 版本一 | 版本二 | OC dispatch_once |
|---|---|---|---|
| 線程安全 | ✅ | ✅ | ✅ |
| 延遲初始化 | ✅ | ✅ | ✅ |
| 防外部實例化 | private init | private init | dispatch_once |
| 推薦度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⚠️ 已棄用 |
單例屬於「全域狀態」,難以測試與解耦。現代 Swift 偏好:
protocol Service { func doWork() }
class RealService: Service { ... }
class MockService: Service { ... }
// 使用時注入具體實現
func run(service: Service) { service.doWork() }
run(service: RealService()) // 生產
run(service: MockService()) // 測試
+sharedInstance 改為 static let shared。dispatch_once,改用靜態常量。private。init() 公開暴露,統一封鎖。