- 若選擇單例,必須有的三個想法
可以被全局訪問
不會被釋放
創(chuàng)建過程只執(zhí)行1次
- 偽單例 和 完整單例
偽單例
1、 獲取單例對象的方法
+ (DataHandle *)sharedDataHandle; // 創(chuàng)建單例對象的方法。類方法 命名規(guī)則: shared + 類名
2、 方法的實現(xiàn)
// 因為實例是全局的 因此要定義為全局變量,且需要存儲在靜態(tài)區(qū),不釋放。不能存儲在棧區(qū)。
static DataHandle *handle = nil;
// 偽單例 和 完整的單例。 以及線程的安全。
// 一般使用偽單例就足夠了 每次都用 sharedDataHandle 創(chuàng)建對象。
+ (DataHandle *)sharedDataHandle
{
// 添加同步鎖,一次只能一個線程訪問。如果有多個線程訪問,等待。一個訪問結(jié)束后下一個。
@synchronized(self){
if (nil == handle) {
handle = [[DataHadle alloc] init];
}
}
return handle;
}
完整的單例:不僅要求我們通過方法獲取的對象是單例,如果有 對該對象進行copy mutableCopy copyWithZone 等操作
- 完整的單例要做到四個方面:
(1).為單例對象實現(xiàn)一個靜態(tài)實例,然后設(shè)置成nil,
(2).構(gòu)造方法檢查靜態(tài)實例是否為nil,是則新建并返回一個實例,
(3).重寫allocWithZone方法,用來保證其他人直接使用alloc和init試圖獲得一個新實例的時候不會產(chǎn)生一個新實例,
(4).適當(dāng)實現(xiàn)copyWithZone,retain,retainCount,release和autorelease 等方法
1.同上
2.方法的實現(xiàn):
@synchronized(self){
if (nil == handle) {
handle = [[super allocWithZone:nil] init]; // 避免死循環(huán)
// 如果 在單例類里面重寫了 allocWithZone 方法 ,在創(chuàng)建單例對象時 使用 [[DataHandle alloc] init] 創(chuàng)建,會死循環(huán)。
}
}
return handle;
- 重寫 allocWithZone copy mutableCopy copyWithZone
防止外界拷貝造成多個實例, 保證實例的唯一性。
注意:如果自己重寫了 allocWithZone 就不要再調(diào)用自身的 alloc 方法,否則會出現(xiàn)死循環(huán)。
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [DataHandle sharedDataHandle];
}
- (id)copy
{
return self;
}
- (id)mutableCopy
{
return self;
}
+ (id)copyWithZone:(struct _NSZone *)zone
{
return self;
}
4、 重寫 alloc retain release autorelease retainCount
+ (instancetype)alloc
{
return [DataHandle sharedDataHandle];
}
// 因為只有一個實例, 一直不釋放,所以不增加引用計數(shù)。無意義。
- (instancetype)retain
{
return self;
}
- (oneway void)release
{
// nothing
}
- (instancetype)autorelease
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax; // 返回整形最大值。
}
——-------------------------------------
實例實現(xiàn)夜間模式
首先創(chuàng)建單例,繼承NSObject,并且創(chuàng)建一個便利構(gòu)造器方法(DKNightVersionManager很有名的)
// @Escapeplan
+ (DKNightVersionManager *) sharedNightVersionManager {
static DKNightVersionManager *instance = nil;
@synchronized(self) {
if (instance == nil) {
instance =[ [DKNightVersionManager alloc] init];
}
}
return instance;
}
// 更準確的寫法
+ (DKNightVersionManager *)sharedNightVersionManager {
static dispatch_once_t once;
static DKNightVersionManager *instance;
dispatch_once(&once, ^{
instance = [self new];
});
return instance;
}
創(chuàng)建一個BOOL觀察狀態(tài)
//添加一個bool屬性,判斷是日間還是夜間
@property (nonatomic, assign) BOOL type
switch 創(chuàng)建并添加方法
UISwitch *mySwitch = [UISwitch new];
// 添加到視圖上
[mySwitch addTarget: self action: @selector(judgeDayOrNight) forControlEvents:UIControlEventValueChanged];
在這VC中執(zhí)行如下操作
- (void)(judgeDayOrNight {
DKNightVersionManager *instance = [DKNightVersionManager sharedNightVersionManager];
if (mySwitch.on) {
instance.type = YES;
//改變?yōu)橐归g的顏色
} else {
instance.type = NO;
//改變成日間的顏色
}
}
在其他VC中應(yīng)有相應(yīng)的改變
// 引單例的頭文件
- (void)viewDidLoad {
DKNightVersionManager *instance = [DKNightVersionManager sharedNightVersionManager];
if (instance.type) {
//改變成夜間模式
} else {
//改變成日間模式
}
}