僅用 dispatch_once 回傳共享實例,無法阻止外部呼叫 [[Singleton alloc] init] 或 [singleton copy] 產生新物件。
@implementation Singleton
static Singleton *_instance = nil;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL] init];
});
return _instance;
}
// 1. 截獲 allocWithZone
+ (id)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
// 2. 截獲 copyWithZone
- (id)copyWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
// 可選:防止多次 release 導致過早釋放
- (oneway void)release { }
- (instancetype)retain { return self; }
- (NSUInteger)retainCount { return NSUIntegerMax; }
@end
Singleton *obj1 = [Singleton sharedInstance]; Singleton *obj2 = [Singleton sharedInstance]; Singleton *obj3 = [[Singleton alloc] init]; Singleton *obj4 = [obj1 copy]; // 所有指標指向同一記憶體位址
allocWithZone: 是記憶體分配的入口,覆寫後直接回傳單例;copyWithZone: 處理 copy/mutableCopy;release/retain/retainCount 可防止手動釋放導致崩潰(ARC 環境下通常不需要)。