1、传统单例模式
2、GCD单例模式
3、用宏实现GCD单例模式
4、用宏实现GCD单例模式,名称随类名变化而变化
单例模式一旦使用,将永远不死。不管是控制器还是类,尽管push,pop还是dismiss都不会死掉,下一次用到时还是第一次创建的那个类。
1、看看传统单例模式的实现,要确保线程安全,一定要锁起来。
// static 修饰的对象,只有在程序结束对才会被释放
static id person;
/**
创建单例的步骤
1.保留一个单例对象的静态实例
2.声明和实现一个类方法,返回一个有值的该类对象
3.重写allocWithZoon方法,做判空处理
*/
// 单例的类方法命名一般用share+当前类名
+ (instancetype)sharedPerson {
// synchronized能保证里面的内容同时只能被一个线程执行
@synchronized(self) {
// 先判断是否为空,如果为空再创建
if (person == nil) {
person = [[self alloc] init];
}
}
return person;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
@synchronized(self) {
if (person == nil) {
person = [super allocWithZone:zone];
}
}
return person;
}
- (id)copyWithZone:(NSZone *)zone {
return person;
}
2、看看GCD实现,我们用的是once函数,它已经确保了线程安全问题
static Car *_car;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_car = [super allocWithZone:zone];
});
return _car;
}
+ (instancetype)sharedCar {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_car = [[self alloc] init];
});
return _car;
}
- (id)copyWithZone:(NSZone *)zone {
return _car;
}
3、用宏实现GCD单例模式,当我们需要实现单例类时,其实代码完全是一样的,这样我们抽成宏,但是这个我们只能用同一的方法,sharedInstance。如果我们想这样,一个person类,那么单例就是sharedPerson,看第四份代码。这里\作用是,让宏识别到后面的代码,因为宏默认只识别它后面一行代码,加\就代表下一行也是
// .h文件
#define SingletonH + (instancetype)sharedInstance;
// .m文件
#define SingletonM \
\
static id _instance;\
\
+ (instancetype)allocWithZone:(struct _NSZone *)zone {\
\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_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;\
}
4、用宏实现GCD单例模式,名称随类名变化而变化。这里需要注意,name都是传过来的,所有在用时.h和.m都要传name
像这样
SingletonH(Car)
SingletonM(Car)
// .h文件
#define SingletonH(name) + (instancetype)shared##name;
// .m文件
#define SingletonM(name) \
\
static id _instance;\
\
+ (instancetype)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:(NSZone *)zone {\
return _instance;\
}