最近在項目中需要用到單例模式(singleton),於是對谷歌了一些資料發現objective-c中的單例不是想象中的,apple官方文檔建議並非如此,代碼量是我好幾倍,但是既然官方建議一定是有道理的,谷歌了寫資料,多數都是建議這么使用,卻沒人對此做詳解
因為沒理解透,用着不踏實,所以決定做些調試,了解透徹!
看完如還有疑問可以進IOS中高級開發群:118623167 和大家交流
按照一般的思路,如下
static MyClass *class = nil;
@implementation MyClass
+(MyClass *)sharedMyClass{
if (!class) {
[[self alloc] init];
}
returnclass;
}
@end
調試發現
MyClass *A = [[MyClass alloc] init];
NSLog(@"A:%@",A);
MyClass *B = [MyClass sharedMyClass];
NSLog(@"B:%@",B);
打印出的是
A:<MyClass: 0x6c72d30>
B:<MyClass: 0x6a87e60>
不是一個內存地址,也就是不是同一個實體
官方如下方式實現
static MyClass *class = nil;
@implementation MyClass
+(MyClass *)sharedMyClass{
@synchronized(self){ //為了確保多線程情況下,仍然確保實體的唯一性
if (!class) {
[[self alloc] init]; //該方法會調用 allocWithZone
}
}
returnclass;
}
+(id)allocWithZone:(NSZone *)zone{
@synchronized(self){
if (!class) {
class = [super allocWithZone:zone]; //確保使用同一塊內存地址
return class;
}
}
returnnil;
}
- (id)copyWithZone:(NSZone *)zone;{
return self; //確保copy對象也是唯一
}
-(id)retain{
return self; //確保計數唯一
}
- (unsigned)retainCount
{
return UINT_MAX; //裝逼用的,這樣打印出來的計數永遠為-1
}
- (id)autorelease
{
return self;//確保計數唯一
}
- (oneway void)release
{
//重寫計數釋放方法
}
@end
再調試
MyClass *A = [[MyClassalloc] init];
NSLog(@"A:%@",A);
MyClass *B = [MyClasssharedMyClass];
NSLog(@"B:%@",B);
MyClass *C = [A copy];
NSLog(@"C:%@",C);
打印出的是
A:<MyClass: 0x6a1e130>
B:<MyClass: 0x6a1e130>
C:<MyClass: 0x6a1e130>
都是指向同一塊內存地址
答案已經出來了
apple建議的方式顯然真正的確保了實體的唯一性