Objective-c单例模式的正确写法--用dispatch 线程安全
单例模式在iOS开发中可能算是最常用的模式之一了,但是由于oc本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦,这里我就抛砖引玉来聊一聊iOS中单例模式的设计思路。关于单例模式更多的介绍请参考这篇文章。
单例顾名思义就是说一个类的实例只能有一个,在java、C++这类语言中,可以通过将构造函数私有化来避免对象的重复创建,但是objective-c却不能够这样做,我们需要通过其他机制来达到这个目的。一般情况下,可能我们写的单例模式是这样的:
#import @interface Singleton : NSObject +(instancetype) shareInstance ; @end #import "Singleton.h" @implementation Singleton static Singleton* _instance = nil; +(instancetype) shareInstance
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init] ;
}) ; return _instance ;
} @end
具体使用:
#import
#import "Singleton.h" int main(int argc, const char * argv[]) {
@autoreleasepool { Singleton* obj1 = [Singleton shareInstance] ;
NSLog(@"obj1 = %@.", obj1) ; Singleton* obj2 = [Singleton shareInstance] ;
NSLog(@"obj2 = %@.", obj2) ; //
Singleton* obj3 = [[Singleton alloc] init] ;
NSLog(@"obj3 = %@.", obj3) ;
}
return 0;
}
输出结果为 :
2014-12-15 16:06:28.344 ObjcSingleton[8847:303] obj1 = .
2014-12-15 16:06:28.346 ObjcSingleton[8847:303] obj2 = .
2014-12-15 16:06:28.346 ObjcSingleton[8847:303] obj3 = .
可以看到,当我们调用shareInstance方法时获取到的对象是相同的,但是当我们通过alloc和init来构造对象的时候,得到的对象却是不一样的。
那么问题就来了,我们通过不同的途径得到不同的对象,显然是不行的。我们必须要确保对象的唯一性,所以我们就需要封锁用户通过alloc和init以及copy来构造对象这条道路。
我们知道,创建对象的步骤分为申请内存(alloc)、初始化(init)这两个步骤,我们要确保对象的唯一性,因此在第一步这个阶段我们就要拦截它。当我们调用alloc方法时,oc内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的。拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象。看代码吧:
#import "Singleton.h" @implementation Singleton static Singleton* _instance = nil; +(instancetype) shareInstance
{
static dispatch_once_t onceToken ;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:NULL] init] ;
}) ; return _instance ;
} +(id) allocWithZone:(struct _NSZone *)zone
{
return [Singleton shareInstance] ;
} -(id) copyWithZone:(struct _NSZone *)zone
{
return [Singleton shareInstance] ;
} @end
再看看效果如何:
main : #import
#import "Singleton.h" int main(int argc, const char * argv[]) {
@autoreleasepool { Singleton* obj1 = [Singleton shareInstance] ;
NSLog(@"obj1 = %@.", obj1) ; Singleton* obj2 = [Singleton shareInstance] ;
NSLog(@"obj2 = %@.", obj2) ; //
Singleton* obj3 = [[Singleton alloc] init] ;
NSLog(@"obj3 = %@.", obj3) ; Singleton* obj4 = [[Singleton alloc] init] ;
NSLog(@"obj4 = %@.", [obj4 copy]) ;
}
return 0;
}
输出结果:
2014-12-15 16:11:24.734 ObjcSingleton[8979:303] obj1 = .
2014-12-15 16:11:24.735 ObjcSingleton[8979:303] obj2 = .
2014-12-15 16:11:24.736 ObjcSingleton[8979:303] obj3 = .
2014-12-15 16:11:24.736 ObjcSingleton[8979:303] obj4 = .
可以看到获取到的对象都是一样的了。
思路就是这样,如果还有更严谨的写法请留言告知。谢谢~
Objective-c单例模式的正确写法--用dispatch 线程安全的更多相关文章
- obj.style.z-index的正确写法
obj.style.z-index的正确写法 今天发现obj.style.z-index在js里面报错,后来才知道在js里应该把含"-"的字符写成驼峰式,例如obj.style.z ...
- 【记录】AutoMapper Project To OrderBy Skip Take 正确写法
AutoMapper:Queryable Extensions 示例代码: using (var context = new orderEntities()) { return context.Ord ...
- C++中虚继承派生类构造函数的正确写法
最近工作中某个软件功能出现了退化,追查下来发现是一个类的成员变量没有被正确的初始化.这个问题与C++存在虚继承的情况下派生类构造函数的写法有关.在此说明一下错误发生的原因,希望对更多的人有帮助. 我们 ...
- 使用runloop阻塞线程的正确写法
使用runloop阻塞线程的正确写法 runloop可以阻塞线程,等待其他线程执行后再执行. 比如: @implementation ViewController{ BOOL end;}…– ( ...
- ***PHP $_FILES函数详解 + PHP文件上传 move_uploaded_file() 参数的正确写法
PHP $_FILES函数详解 在PHP中上传一个文件建一个表单要比ASP中灵活得多.具体的看代码. 如: 复制代码代码如下: <form enctype="multipart/fo ...
- jquery中获取radio选中值的正确写法
错误写法: //只在IE下有作用,其他浏览器均获取的为第一个单选框的值 $('input[type=radio]').val(); 正确写法为: //兼容所有浏览器写法 $('input[type=r ...
- ibatis使用iterate实现批量插入insert正确写法
由于想批量入库提升效率,最近实现了ibatis的批量插入,结果一直报错 :StringIndexOutOfBoundsException ,原来是value中的格式不正确. 本人邮箱:techqu@1 ...
- 单例模式,reorder详解,线程安全,双检查锁
单例模式,分为饿汉式单例 和 懒汉式单例. 先把本类对象所需内存在main函数执行前就new出来,这是饿汉式单例. 个人思考: 为什么饿汉式不独霸天下,还有什么必要去研究使用cpp11上支持的双检查锁 ...
- Android系统--输入系统(十二)Dispatch线程_总体框架
Android系统--输入系统(十二)Dispatch线程_总体框架 1. Dispatch线程框架 我们知道Dispatch线程是分发之意,那么便可以引入两个问题:1. 发什么;2. 发给谁.这两个 ...
随机推荐
- python第四讲
三元运算符: 三元运算又叫三目运算,是对简单的条件语句的缩写. 书写格式: n1 = 值1 if 条件 else 值2 # 如果条件成立,那么将 “值1” 赋值给n1变量,否则,将“值2”赋值给n1变 ...
- iOS 获取手机 唯一标识
存贮在keychainQuery 可以统计用户使用情况 -(void)gatherMessage{ //采集用户设备信息 NSUserDefaults *userDefaults=[NSUserDef ...
- JS地区四级级联
<script type="text/javascript" src="../js/jsAddress.js"></script> &l ...
- [办公自动化]计算机突然断电,微软office文档(有asd文件)如何恢复?
今天同事使用office软件时,突然故障.结果他忙了半天的word文档内容都找不见了. 经过查找,在其硬盘根目录找到了asd文档. 但是用当前版本的word和高版本的word软件都无法打开. 又查找了 ...
- Java 负载均衡
什么是负载均衡 负载均衡,英文 名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助.通过某种 负载分 ...
- 用过滤器Filter判断用户是否登陆
用过滤器Filter判断用户是否登陆 WEB.XML <!-- 用户session的 键 sessionKEY --> <context-param> <param- ...
- Iphone 启动图的尺寸
APP图标设置 - 取Images.xcassets中的AppIcon, 图标尺寸 29pt * 2x => 58 * 5829pt * 3x => 87 * 8740pt * 2x =& ...
- 六:多线程--自定义NSOperation
一.实现一个简单的tableView显示效果 实现效果展示: 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UITableViewController. 3 // ...
- [Codeforces 507E] Breaking Good
[题目链接] https://codeforces.com/contest/507/problem/E [算法] 首先BFS求出1到其余点的最短路 , N到其余点的最短路,记为distA[]和dist ...
- 洛谷 P1071 潜伏者 —— 模拟
题目:https://www.luogu.org/problemnew/show/P1071 按题意模拟即可. 代码如下: #include<iostream> #include<c ...