- 概念相關
(1)單例模式
在程序運行過程,一個類只有一個實例
(2)使用場合
在整個應用程序中,共享一份資源(這份資源只需要創建初始化1次)
- 2 ARC實現單例
(1)步驟
01 在類的內部提供一個static修飾的全局變量
02 提供一個類方法,方便外界訪問
03 重寫+allocWithZone方法,保證永遠都只為單例對象分配一次內存空間
04 嚴謹起見,重寫-copyWithZone方法和-MutableCopyWithZone方法
(2)相關代碼
//提供一個static修飾的全局變量,強引用著已經實例化的單例對象實例
static AZTools *_instance;
//類方法,返回一個單例對象
+(instancetype)shareTools
{
//注意:這里建議使用self,而不是直接使用類名Tools(考慮繼承)
return [[self alloc]init];
}
//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//使用GCD中的一次性代碼
// static dispatch_once_t onceToken;
// dispatch_once(&onceToken, ^{
// _instance = [super allocWithZone:zone];
// });
//使用加鎖的方式,保證只分配一次存儲空間
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
/*
1. mutableCopy 創建一個新的可變對象,并初始化為原對象的值,新對象的引用計數為 1;
2. copy 返回一個不可變對象。分兩種情況:(1)若原對象是不可變對象,那么返回原對象,并將其引用計數加 1 ;(2)若原對象是可變對象,那么創建一個新的不可變對象,并初始化為原對象的值,新對象的引用計數為 1。
*/
//讓代碼更加的嚴謹
-(nonnull id)copyWithZone:(nullable NSZone *)zone
{
// return [[self class] allocWithZone:zone];
return _instance;
}
-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone
{
return _instance;
}
- 3 MRC實現單例
(1)實現步驟
01 在類的內部提供一個static修飾的全局變量
02 提供一個類方法,方便外界訪問
03 重寫+allocWithZone方法,保證永遠都只為單例對象分配一次內存空間
04 嚴謹起見,重寫-copyWithZone方法和-MutableCopyWithZone方法
05 重寫release方法
06 重寫retain方法
07 建議在retainCount方法中返回一個最大值
(2)配置MRC環境知識
01 注意ARC不是垃圾回收機制,是編譯器特性
02 配置MRC環境:build setting ->搜索automatic ref->修改為NO
(3)相關代碼
//提供一個static修飾的全局變量,強引用著已經實例化的單例對象實例
static AZTools *_instance;
//類方法,返回一個單例對象
+(instancetype)shareTools
{
//注意:這里建議使用self,而不是直接使用類名Tools(考慮繼承)
return [[self alloc]init];
}
//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//使用GCD中的一次性代碼
// static dispatch_once_t onceToken;
// dispatch_once(&onceToken, ^{
// _instance = [super allocWithZone:zone];
// });
//使用加鎖的方式,保證只分配一次存儲空間
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
//讓代碼更加的嚴謹
-(nonnull id)copyWithZone:(nullable NSZone *)zone
{
// return [[self class] allocWithZone:zone];
return _instance;
}
-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone
{
return _instance;
}
//在MRC環境下,如果用戶retain了一次,那么直接返回instance變量,不對引用計數器+1
//如果用戶release了一次,那么什么都不做,因為單例模式在整個程序運行過程中都擁有且只有一份,程序退出之后被釋放,所以不需要對引用計數器操作
-(oneway void)release
{
}
-(instancetype)retain
{
return _instance;
}
//慣用法,有經驗的程序員通過打印retainCount這個值可以猜到這是一個單例
-(NSUInteger)retainCount
{
return MAXFLOAT;
}
- 4 通用版本
- 宏定義中可以在
AZSingleH(name)
后傳入一個參數name,+ (instancetype)share##name
方法名跟隨傳入的name參數確定 - 宏定義中不能使用條件編譯,可以將ARC和MRC分開寫成兩個宏
- 只需將下面的文件包含到頭文件,分別在.h文件中引入
AZSingleH(name)
,在.m文件中引入AZSingleM(name)
(后面name參數根據自己需要填寫),即可實現通用 - 每一段換行都需要用轉義字符
\\
標記
- 宏定義中可以在
#define AZSingleH(name) +(instancetype)share##name;
#if __has_feature(objc_arc)
//ARC
#define AZSingleM(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 AZSingleM(name) static id _instance;\
\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
@synchronized (self) {\
if (_instance == nil) {\
_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