单例作为一种设计模式,它的作用可以在全局同一个类仅仅存在一个实例对象,从而节约了内存。
应用场景:多个模块都需要使用到同样的对象,例如用户的登录信息,一个播放器(音频、视频),提示框等等一些可以在整个App中都有可能多次用到的类。
在创建单例的时候,需要考虑线程之间的问题。当开辟了两条子线程同时访问一块区域的时候,就会创建两个实例对象,这时需要在创建对象的方法中添加一把锁,在一条线程未创建完一个实例对象之前,另外一条线程始终等待着,这样就能创建一个唯一的实例对象。
1.不使用GCD创建一个单例
新建一个Person类
在.h文件中,声明一个单例创建方法
+ (instancetype)shareInstance;
在.m文件中,实现方法
static id _instance; /**< 设置一个全局变量,作为次对象的返回 */
/**
* 单例的创建
*/
+ (instancetype)shareInstance {
// 防止同时创建对象,加把互斥锁,锁的对象要一致
@synchronized (self) {
if (_instance == nil) {
_instance = [[self alloc] init];
}
}
return _instance;
}
为了使用init创建一个实例对象也能创建出唯一的重写系统 allocWithZone 方法
/**
* 重写allocWithZone的方法,通过init方法创建对象也是一个单例对象
*/
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
@synchronized (self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
利用互斥锁来实现单例的创建,查看结果
2.利用GCD的方式创建单例
static Student *_instance;
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [[self alloc] init];
}
});
return _instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
});
return _instance;
}
结果
3.利用模板去创建一个单例
// .h
#define singleton_interface(class) + (instancetype)shared##class;
// .m
#define singleton_implementation(class) \
static class *_instance; \
\
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
\
return _instance; \
} \
\
+ (instancetype)shared##class \
{ \
if (_instance == nil) { \
_instance = [[class alloc] init]; \
} \
\
return _instance; \
}
新建一个Teacher类
.h文件
#import "Singleton.h"
@interface Teacher : NSObject
singleton_interface(Teacher);
@end
.m文件
@implementation Teacher
singleton_implementation(Teacher);
@end
效果