MRC下单例模式的内存问题与ARC实现

单例模式保证一个类只能拥有一个静态的实例,类负责创建与维护这个实例,并提供一个统一的静态(类方法)访问方式,并封锁了这个类外部的代码对这个类对象的创建。

.h文件:

1 #import <Foundation/Foundation.h>
2 
3 @interface Singleton : NSObject
4 @property (nonatomic, copy) NSString *name;
5 + (Singleton *) sharedInstance;
6 @end

这里定义了一个类方法来获取单例对象的实例。

.m文件则比较复杂,首先要负责这个对象的创建:

 1 #import "Singleton.h"
 2 
 3 @implementation Singleton
 4 
 5 static Singleton *_sharedInstance = nil;
 6 + (Singleton *) sharedInstance {
 7     if (_sharedInstance == nil) {
 8         _sharedInstance = [[super allocWithZone:nil] init];
 9     }
10     return _sharedInstance;
11 }
12 
13 +(id)allocWithZone:(struct _NSZone *)zone {
14     return [[self sharedInstance] retain];
15 }

这里令人费解的是红字部分,为什么不直接alloc一个Singletone呢?

其实allocWithZone:nil就等价于alloc,只是这里alloc的是父类NSObject,这样做目的是把子类Singleton的allocWithZone拆解出去,拆解出来是为了复写。

之所以要复写,是为了堵住内存分配的漏洞,因为除了+sharedInstance方法之外,用户还可能在外部程序当中alloc一个Singleton对象,而OC语言并不支持java/C#当中的将构造函数私有化。

所以,子类复写allocWithZone的目的就显而易见、无需多言了。

到这里还没有结束,还需要堵住其他内存管理的漏洞,一是保证直接alloc的结果和使用sharedInstance方法的效果一样,二是令release无效:

 1 -(id)copyWithZone:(NSZone *)zone {
 2     return self;
 3 }
 4 
 5 -(id)init {
 6     if (_sharedInstance) {
 7         return _sharedInstance;
 8     }
 9     self = [super init];
10     return self;
11 }
12 
13 - (id)retain {
14     return self;
15 }
16 
17 -(void)release {
18     // Do nothing
19 }
20 
21 -(id)autorelease {
22     return self;
23 }
24 
25 -(NSUInteger)retainCount {
26     return NSUIntegerMax;
27 }

这样就形成了一个中规中矩的、满足内存管理的单例模式,代码显得十分啰嗦,本质原因在于OC对private支持的不好,导致我们做了很多额外工作。

上面的代码不是线程安全的,如果需要保证单例对象的线程安全性,则需要写同步锁代码。

ARC下的单例相对简单:

1 + (id)sharedInstance
2 {
3   static dispatch_once_t pred = 0;
4   __strong static id _sharedObject = nil;
5   dispatch_once(&pred, ^{
6     _sharedObject = [[self alloc] init]; // or some other init method
7   });
8   return _sharedObject;
9 }

更有甚者搞了一个宏:http://lukeredpath.co.uk/blog/2011/07/01/a-note-on-objective-c-singletons/

转载于:https://www.cnblogs.com/Steak/p/3537798.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值