单例
1、什么是单例模式
简单的来说,一个单例类,在整个程序中只有一个实例,并且提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序(APP)退出时由系统自动释放这部分内存。
2.系统为我们提供的单例类有哪些?
UIApplication(应用程序实例类)
NSNotificationCenter(消息中心类)
NSFileManager(文件管理类)
NSUserDefaults(应用程序设置)
NSURLCache(请求缓存类)
NSHTTPCookieStorage(应用程序cookies池)
3.在哪些地方会用到单例模式
一般来说 经常调用的类,如工具类、公共跳转类等,采用单例模式
4.重复初始化单例类会怎样?
程序直接崩溃 因为一个单例类只能初始化一次
5.单例模式的优缺点
优:
1)、在整个程序中只会实例化一次,所以在程序如果出了问题,可以快速的定位问题所在;
2)、由于在整个程序中只存在一个对象,节省了系统内存资源,提高了程序的运行效率;
缺:
1)、不能被继承,不能有子类;
2)、不易被重写或扩展;
3)、同时,由于单例对象只要程序在运行中就会一直占用系统内存,该对象在闲置时并不能销毁,在闲置时也消耗了系统内存资源;
6.单例类的生命周期
下面的表格展示了程序中中不同的变量在手机存储器中的存储位置
一个单例类在程序中只能初始化一次,为了保证在使用中始终都是存在的,所以单例是在存储器的全局区域,在编译时分配内存,只要程序还在运行就会一直占用内存,在APP结束后由系统释放这部分内存内存。
7.1如何单例类ARC (分MRC ARC)
ARC实现单例过程:
1.在类的内部提供一个static修饰的全局变量static SingletonVC * _singletonVC;;
2 提供一个类方法,方便外界访问
3 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间
4.严谨起见,重写-copyWithZone方法和-MutableCopyWithZone方法
单例三种写法
第一种:GCD的一次函数(dispatch_once_t)
第二种:线程锁
第三种:懒加载模式 (不推荐使用这种方法,线程不安全)
第一种:GCD的一次函数(dispatch_once_t)
#import "SingletonVC.h"
// 创建静态对象 防止外部访问
static SingletonVC * _singletonVC;
@implementation SingletonVC
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
// 一次函数
dispatch_once(&onceToken, ^{
if (_singletonVC == nil) {
_singletonVC = [super allocWithZone:zone];
}
});
return _singletonVC;
}
+ (instancetype)share{
return [[self alloc] init];
}
@end
第二种:线程锁
#import "SingletonVC.h"
// 创建静态对象 防止外部访问
static SingletonVC * _singletonVC;
@implementation SingletonVC
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
//线程锁
@synchronized (self) {
if (_singletonVC == nil) {
_singletonVC = [super allocWithZone:zone];
}
}
return _singletonVC;
}
+ (instancetype)share{
return [[self alloc] init];
}
@end
第三种:懒加载模式 (不推荐使用这种方法,线程不安全)
#import "SingletonVC.h"
static SingletonVC * _singletonVC;
@implementation SingletonVC
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
if (_singletonVC == nil) {
_singletonVC = [super allocWithZone:zone];
}
return _singletonVC;
}
+ (instancetype)share{
return [[self alloc] init];
}
@end
7.2如何单例类MRC
MRC单例实现步骤
1 在类的内部提供一个static修饰的全局变量
2 提供一个类方法,方便外界访问
3 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间
4 严谨起见,重写-copyWithZone方法和-MutableCopyWithZone方法
5 重写release方法
6 重写retain方法
7 建议在retainCount方法中返回一个最大值
配置MRC环境
1 注意ARC不是垃圾回收机制,是编译器特性
2 配置MRC环境:build setting ->搜索automatic ref->修改为N0
MRC中单例代码实现
配置好MRC环境之后,在ARC代码基础上重写下面的三个方法即可
-(oneway void)release
{
}
-(instancetype)retain
{
return _instance;
}
-(NSUInteger)retainCount
{
return MAXFLOAT;
}
8.一劳永逸,单例模式的优化
1:如何写一份单例代码在ARC和MRC环境下都适用?
2:如何使一份单例代码可以多个类共同使用
为了解决这两个问题,我们可以在PCH文件使用代参数的宏和条件编译
利用条件编译来判断是ARC还是MRC环境
#if __has_feature(objc_arc)
//如果是ARC,那么就执行这里的代码1
#else
//如果不是ARC,那么就执行代理的代码2
#endif
#define singleH(name) +(instancetype)share##name;
#if __has_feature(objc_arc)
#define singleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}
#else
#define singleM static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
\
+(instancetype)shareTools\
{\
return [[self alloc]init];\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
return MAXFLOAT;\
}
#endif
任何项目中,当我们要使用单例类的时候只要在项目中导入PCH文件然后在.h文件中调用singleH(类名),在.m文件中调用singleM(类名),创建类时直接调用share类名方法即可。
浙公网安备 33010602011771号