概述
單例顧名思義就是只有一個(gè)實(shí)例,單例模式可以確保一個(gè)類只有一個(gè)實(shí)例;
單例的實(shí)例是用static修飾的,所以在內(nèi)存中的位置是常量區(qū);
單例的生命周期跟隨者Appdelegate的銷毀而銷毀
代碼實(shí)現(xiàn)
創(chuàng)建一個(gè)繼承自NSObject的類及其初始化方法
.h文件代碼,一個(gè)屬性,一個(gè)開放的初始化方法
@interface ZHSignal : NSObject
+(instancetype)shareSignal;
/// 姓
@property(nonatomic, copy)NSString *surname;
@end
.m文件代碼,聲明一個(gè)靜態(tài)全局變量,作為實(shí)例對(duì)象,實(shí)現(xiàn)初始化方法
static ZHSignal *zh_signal = nil;
@implementation ZHSignal
+(instancetype)shareSignal{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
zh_signal = [[ZHSignal alloc] init];
});
return zh_signal;;
}
@end
這樣一個(gè)單例基本完成。使用如下
ZHSignal *sin0 = [ZHSignal shareSignal];
sin0.surname = @"趙";
ZHSignal *sin1 = [[ZHSignal alloc] init];
ZHSignal *sin2 = [ZHSignal shareSignal];
NSLog(@"%@-%@-%@",sin0.surname,sin1.surname,sin2.surname);
打印結(jié)果如下:
2018-10-29 11:33:51.996792+0800 test[2893:53029] 趙-(null)-趙
很顯然,掉用alloc方法無法滿足單例的要求。那就需要改變代碼,往下看。
重寫allocWithZone
很可能外面會(huì)調(diào)用alloc和new來實(shí)例化單例,這回導(dǎo)致單例類有多個(gè)實(shí)例的情況,因?yàn)檫@兩個(gè)方法,最終都會(huì)調(diào)用allocWithZone方法,所以重寫這個(gè)方法可以達(dá)到目的。
.m文件代碼改動(dòng)如下:
+(instancetype)shareSignal{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
zh_signal = [[super allocWithZone:NULL]init];
});
return zh_signal;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
return [self shareSignal];
}
這樣就可以避免調(diào)用alloc和new方法導(dǎo)致一系列問題了。
重寫copy和mutableCopy方法
在OC中的,除了一些特別的類是系統(tǒng)已經(jīng)支持copy與mutableCopy的,其它的類是需要開發(fā)者自己遵守NSCopying與NSMutableCopying這兩個(gè)協(xié)議,然后實(shí)現(xiàn)其協(xié)議方法來支持copy與mutableCopy方法的。如果沒有實(shí)現(xiàn)這兩個(gè)協(xié)議方法的話,直接調(diào)用copy或者mutableCopy方法是會(huì)直接crash的,即使這兩個(gè)方法是在NSObject中公開的。調(diào)用copy和mutableCopy,其底層是調(diào)用copyWithZone和mutableCopyWithZone,所以代碼做如下修改
.h文件遵循兩個(gè)協(xié)議
@interface ZHSignal : NSObject<NSCopying,NSMutableCopying>
.m文件實(shí)現(xiàn)兩個(gè)協(xié)議方法
-(id)copyWithZone:(NSZone *)zone{
return zh_signal;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return zh_signal;
}
當(dāng)然,這里其實(shí)也可以換一種思路,既不遵循協(xié)議,也不實(shí)現(xiàn)協(xié)議方法,而是實(shí)現(xiàn)copy和mutableCopy方法,如下:
-(id)copy{
return zh_signal;
}
-(id)mutableCopy{
return zh_signal;
}
這樣同樣能達(dá)到目的。
MRC的情況下的單例模式
需要重寫幾個(gè)方法,如下
// 不做release
- (oneway void)release {
}
// retain之后還是自己
- (id)retain {
return self;
}
// 計(jì)數(shù)器永遠(yuǎn)為1
- (NSUInteger)retainCount {
return 1;
}
// 防止被放進(jìn)自動(dòng)計(jì)數(shù)池釋放
- (id)autorelease {
return self;
}
單例模式做到這樣就完美了&