MRC下单例模式的内存问题与ARC实现
单例模式保证一个类只能拥有一个静态的实例,类负责创建与维护这个实例,并提供一个统一的静态(类方法)访问方式,并封锁了这个类外部的代码对这个类对象的创建。
.h文件:
#import <Foundation/Foundation.h> @interface Singleton : NSObject
@property (nonatomic, copy) NSString *name;
+ (Singleton *) sharedInstance;
@end
这里定义了一个类方法来获取单例对象的实例。
.m文件则比较复杂,首先要负责这个对象的创建:
#import "Singleton.h" @implementation Singleton static Singleton *_sharedInstance = nil;
+ (Singleton *) sharedInstance {
if (_sharedInstance == nil) {
_sharedInstance = [[super allocWithZone:nil] init];
}
return _sharedInstance;
} +(id)allocWithZone:(struct _NSZone *)zone {
return [[self sharedInstance] retain];
}
这里令人费解的是红字部分,为什么不直接alloc一个Singletone呢?
其实allocWithZone:nil就等价于alloc,只是这里alloc的是父类NSObject,这样做目的是把子类Singleton的allocWithZone拆解出去,拆解出来是为了复写。
之所以要复写,是为了堵住内存分配的漏洞,因为除了+sharedInstance方法之外,用户还可能在外部程序当中alloc一个Singleton对象,而OC语言并不支持java/C#当中的将构造函数私有化。
所以,子类复写allocWithZone的目的就显而易见、无需多言了。
到这里还没有结束,还需要堵住其他内存管理的漏洞,一是保证直接alloc的结果和使用sharedInstance方法的效果一样,二是令release无效:
-(id)copyWithZone:(NSZone *)zone {
return self;
}
-(id)init {
if (_sharedInstance) {
return _sharedInstance;
}
self = [super init];
return self;
}
- (id)retain {
return self;
}
-(void)release {
// Do nothing
}
-(id)autorelease {
return self;
}
-(NSUInteger)retainCount {
return NSUIntegerMax;
}
这样就形成了一个中规中矩的、满足内存管理的单例模式,代码显得十分啰嗦,本质原因在于OC对private支持的不好,导致我们做了很多额外工作。
上面的代码不是线程安全的,如果需要保证单例对象的线程安全性,则需要写同步锁代码。
ARC下的单例相对简单:
+ (id)sharedInstance
{
static dispatch_once_t pred = ;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init]; // or some other init method
});
return _sharedObject;
}
更有甚者搞了一个宏:http://lukeredpath.co.uk/blog/2011/07/01/a-note-on-objective-c-singletons/
MRC下单例模式的内存问题与ARC实现的更多相关文章
- iOS: ARC & MRC下string内存管理策略探究
ARC & MRC下string内存管理策略探究 前两天跟同事争论一个关于NSString执行copy操作以后是否会发生变化,两个人整了半天,最后写代码验证了一下,发现原来NSString操作 ...
- 1.ARC下是否有内存溢出等问题 2.@property参数 3.#import和@class的区别
1.ARC下是否有内存溢出等问题? 答案:必须要担心啊,ARC也不是万能的.答案:必须要担心啊,ARC也不是万能的.这里主要是涉及到集合类的数据类型 比如数组,我们定义了一个可变数组muarr1, ...
- OC的内存管理(二)ARC
指针: 指向内存的地址指针变量 存放地址的变量指针变量值 变量中存放的值(地址值)指针变量指向的内存单元值 内存地址指向的值1):强指针:默认的情况下,所有的指针都是强指针,关键字strong ):弱 ...
- linux 下 取进程占用内存(MEM)最高的前10个进程
# linux 下 取进程占用 cpu 最高的前10个进程ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head # linux 下 取进程占用内存 ...
- Linux 下增大tomcat内存
我的服务器的配置: # OS specific support. $var _must_ be set to either true or false. JAVA_OPTS="-Xms10 ...
- 32位Windows7上8G内存使用感受+xp 32位下使用8G内存 (转)
32位Windows7上8G内存使用感受+xp 32位下使用8G内存 博客分类: Windows XPWindowsIE企业应用软件测试 我推荐做开发的朋友:赶快加入8G的行列吧....呵呵..超爽 ...
- (转)Linux下tomcat JVM内存设置步骤
java.lang.OutOfMemoryError: PermGen space java.lang.OutOfMemoryError: Java heap space -------------- ...
- [转帖]linux下CPU、内存、IO、网络的压力测试,硬盘读写速度测试,Linux三个系统资源监控工具
linux下CPU.内存.IO.网络的压力测试,硬盘读写速度测试,Linux三个系统资源监控工具 https://blog.51cto.com/hao360/1587165 linux_python关 ...
- iOS下单例模式实现(一)(objective-c arc gcd)
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 这里主要介绍下在arc下,利用gcd实现单例. 第一步:声明一个静态实例 static SoundTool *_instan ...
随机推荐
- javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记
1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...
- [转]easyui常用控件及样式收藏
CSS类定义: div easyui-window window窗口样式 属性如下: 1) modal:是否生成模态窗口.tru ...
- python----设置默认编码
问题:python的默认编码是ascii.在处理中文的时候可能会出现乱码的情况:这个时候我们就需要把编码设置为对应的编码了. 解决方案: 对python文件的头部做如下修改 import sys re ...
- [问题解决] 程序部署到Linux服务器乱码
错误: 在windows下开发的eclipse项目需要用java mail发送邮件,在将整个项目部署到linux服务器之后发送的邮件出现了乱码. 发生场景: Linux服务器下的Java mail程序 ...
- sim卡中电话本(ADN)的简要格式
ADN的格式 ADN存放于sim卡下面3f00/7f10/6f3a,记录文件格式,其最小记录格式为14,最长为255(?),记录个数最大为255(?) 其后数14个字节是必有的,其前12个字节是电话号 ...
- 紫薇~还记得大明湖畔的HTML5智力拼图吗?
曲线谜团是非常有趣的HTML5智力游戏,据说超过多少分会有惊喜,游戏简单易操作,偶尔抛弃那种杀死脑细胞的大型游戏,玩玩这种简单经典的益智小游戏,放松放松,也是不错的选择嘛-将游戏 通过 统一开发环境( ...
- 记录一下八款开源 Android 游戏引擎
记录一下八款开源 Android 游戏引擎 虽然android学了点点,然后现在又没学了(我为啥这么没有恒心呢大哭).以后有时间还是要继续学android的,一定要啊!虽然现在没学android游戏编 ...
- Java程序员快速入门Go语言
这篇文章帮助Java程序员快速入门Go语言. 转载至 开源中国社区. http://www.oschina.net 本文将以一个有代表性的例子为开始,以此让Java程序员对Go语言有个初步认识,随后将 ...
- VC++2008 用空工程创建 DLL
VC++2008 用空工程创建 DLL 一.创建 DLL 工程项目: 1)点击菜单[File] -> [New] -> [Project...] 弹出 “New Project” 对话框: ...
- MyEclipse修改
MyEclipse设置编码方式 http://www.cnblogs.com/susuyu/archive/2012/06/27/2566062.html Eclipse添加Spket插件实现ExtJ ...