objective-c 单例模式详解

最近在项目中需要用到单例模式(singleton),于是对谷歌了一些资料发现objective-c中的单例不是想象中的,apple官方文档建议并非如此,代码量是我好几倍,但是既然官方建议一定是有道理的,谷歌了写资料,多数都是建议这么使用,却没人对此做详解

因为没理解透,用着不踏实,所以决定做些调试,了解透彻!

按照一般的思路,如下

01 static MyClass *class = nil;
02  
03 @implementation MyClass
04  
05 +(MyClass *)sharedMyClass{
06  
07     if (!class) {
08  
09        class = [[self alloc] init];
10  
11     }
12  
13     return class;
14  
15 }
16  
17 @end

调试发现

MyClass *A = [[MyClass allocinit];

NSLog(@"A:%@",A);

MyClass *B = [MyClass sharedMyClass];

NSLog(@"B:%@",B);

打印出的是

A:<MyClass: 0x6c72d30>

B:<MyClass: 0x6a87e60>

不是一个内存地址,也就是不是同一个实体

 

官方如下方式实现

01 static MyClass *class = nil;
02  
03 @implementation MyClass
04  
05 +(MyClass *)sharedMyClass{
06     @synchronized (self){  //为了确保多线程情况下,仍然确保实体的唯一性
07         if (!class) {
08             [[self alloc] init]; //该方法会调用 allocWithZone
09         }
10     }
11     return class;
12 }
13   
14  
15 +(id)allocWithZone:(NSZone *)zone{
16     @synchronized (self){
17         if (!class) {
18             class = [super allocWithZone:zone]; //确保使用同一块内存地址
19             return class;
20         }
21     }
22     return nil;
23 }
24  
25 - (id)copyWithZone:(NSZone *)zone;{
26     return self; //确保copy对象也是唯一
27 }
28  
29 -(id)retain{
30     return self; //确保计数唯一
31 }
32  
33 - (unsigned)retainCount
34 {
35    return UINT_MAX;  //装逼用的,这样打印出来的计数永远为-1
36 }
37  
38 - (id)autorelease
39 {
40     return self;//确保计数唯一
41 }
42  
43 - (oneway void)release
44  
45 {
46      //重写计数释放方法
47 }
48  
49 @end

 

再调试

MyClass *A = [[MyClassallocinit];

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建议的方式显然真正的确保了实体的唯一性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值