在开发中经常会用到单例,它在整个程序的运行周期里面只会被创建一次,只要程序没有结束,它就不会被释放!创建单例的两种方式如下:
一、GCD方式创建单例
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToke;
dispatch_once(&onceToke, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
二、互锁创建单例的方法
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
+ (instancetype)sharedInstance
{
@synchronized(self) {
if (_instance == nil) {
_instance = [[self alloc] init];
}
}
return _instance;
}
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
说明:
1、CGD创建单例的方式中,用dispatch_once保证了里面的代码只能被执行一次,如果程序再次走到这个方法的时候会直接返回创建好的实例对象,这样保证了只会创建一个实例对象;
2、 在互锁创建单例的方式中,@synchronized相当于给括起来的任务加了一把锁,如果当前任务正在执行,另外一条线程执行到@synchronized时候就会进入睡眠模式,等当前任务执行完后才会执行,此时_instance已经被创建,不为nil,所以直接返回_instance,这样也保证了只会创建一个实例对象。但是在多线程开发中,这种方式会影响程序的性能,建议用第一种
总结:
在多线程开发中互锁的方式会影响项目的性能,建议用GCD的方式!
通过GCD创建单例的方式是固定不变的,为了方便以后快速实现单例,可以把创建方式定义成宏。
// .h文件
#define singleton_h(name) + (instancetype)shared##name;
// .m文件
#define singleton_m(name) \
static id _instance; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[self alloc] init]; \
}); \
return _instance; \
} \
\
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instance; \
}\
\
- (id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}