- 1.1 概念
(1)单例模式
(1.1)在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
(1.2)方便地控制了实例个数,并节约系统资源
(1.3)单例是不可以用继承的,因为不能父类与子类共用一个全局变量
(2)使用场合
在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次);
可以理解为当需要一个24小时响应的“马仔”帮你实现某些功能时,使用单例。
(3)约束-不要滥用单例模式
1. 单例是一种全局状态,意味着App的任何地方都可以和这个单例进行交互,无形中增加了代码的耦合
2. 单例的生命周期难以控制,虽然可以在单例中提供方法设为nil进行释放。
- 1.2 实现单例(在ARC与MRC中均可执行)
(1)实现步骤
01 在类的内部提供一个static修饰的全局变量
02 重写+allocWithZone方法,保证永远都只为单例对象分配一次内存空间
03 提供一个类方法,方便外界访问
04 严谨起见,重写-copyWithZone方法和-MutableCopyWithZone方法
05 通过条件编译判断是否是ARC{__has_feature(objc_arc)},若是,则不再执行代码,否则执行下述06-09代码
06 重写release方法
07 重写retain方法
08 建议在retainCount方法中返回一个最大值
09 结束条件编译
(2)如果在MRC中运行,需配置MRC环境知识
01 注意ARC不是垃圾回收机制,是编译器特性
02 配置MRC环境:build setting ->搜索automatic ref->修改为NO
(3)相关代码
- allocWithZone方法中加锁或GCD一次性代码详见多线程
//提供一个static修饰的全局变量,强引用着已经实例化的单例对象实例 static id _instance; //保证永远只分配一次存储空间 +(instancetype)allocWithZone:(struct _NSZone *)zone { //使用GCD中的一次性代码 // static dispatch_once_t onceToken; // dispatch_once(&onceToken, ^{ // _instance = [[super allocWithZone:zone]init]; // }); //使用加锁的方式,保证只分配一次存储空间 @synchronized(self) { if (_instance == nil) { _instance = [super allocWithZone:zone]; } } return _instance; } //类方法,返回一个单例对象 +(instancetype)shareTools { //注意:这里建议使用self,而不是直接使用类名Tools(考虑继承) return [[self alloc]init]; } //让代码更加的严谨 -(nonnull id)copyWithZone:(nullable NSZone *)zone { // return [[self class] allocWithZone:zone]; return _instance; } -(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone { return _instance; } #if __has_feature(objc_arc) //如果是ARC环境下 #else //如果是MRC环境下 //在MRC环境下,如果用户retain了一次,那么直接返回instance变量,不对引用计数器+1 //如果用户release了一次,那么什么都不做,因为单例模式在整个程序运行过程中都拥有且只有一份,程序退出之后被释放,所以不需要对引用计数器操作 -(oneway void)release { } -(instancetype)retain { return _instance; } //惯用法,有经验的程序员通过打印retainCount这个值可以猜到这是一个单例 -(NSUInteger)retainCount { return MAXFLOAT; } #endif
单例封装宏
01 注意条件编译的代码不能包含在宏定义里面
02 宏定义的代码只需要写一次就好,之后直接拖到项目中用就OK
- .h文件
#define SingleH(name) +(instancetype)share##name;
- .m文件
#if __has_feature(objc_arc)
//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
//mrc
#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;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
return MAXFLOAT;\
}
#endif