什么是单例
一个类只允许有一个实例,在整个程序中需要多次使用,共享同一份资源的时候,就可以创建单例,一般封装成工具类使用,苹果封装成单例常用的什么情况下使用单例
- 类只能有一个实例,并且必须从一个为人熟知的访问点对其进行访问,比如类工厂方法
- 这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端的代码
设计要点
- 某个类只有一个实例
- 必须自行创建这个对象
- 必须自行向整个系统提供这个实例
- 这个方法一定是一个静态类
ARC中
+ (instancetype)shareInstance
{
Tools *instance = [[self alloc] init];
return instance;
}
//创建一个全局变量,控制对象只调用一次
static Tools *_instance = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
//所有的创建方法都会调用该方法,只需要在这里控制当前对象之创建一次即可
if (_instance == nil) {
_instance = [[super allocWithZone:zone] init];
}
return _instance;
}
//用到copy要给类加协议,因为是单例,所以直接返回就行了
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
但是该方法在多线程中会出毛病,只需要在重写allocWithZone中这样修改
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
//再多线程中也只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:zone] init];
});
return _instance;
}
MRC
只需要多重写release,retain,retainCount
- (oneway void)release
{
//需要让程序在整个过程中只有一个实例,什么都不做
}
- (instancetype)retain
{
return _instance;
}
- (NSUInteger)retainCount
{
//方便沟通,不会返回1,返回一个巨大的值
return MAXFLOAT;
}
单例宏抽取
反斜杠代表一行
#define interfaceSingleton(name) +(instancetype)share##name
//判断是ARC还是MRC
#if __has_feature(objc_arc)
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
#else
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (oneway void)release \
{ \
} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return MAXFLOAT; \
}
#endif