單例(singleton)

  • 若選擇單例,必須有的三個想法

可以被全局訪問
不會被釋放
創(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
{
    // 添加同步鎖,一次只能一個線程訪問。如果有多個線程訪問,等待。一個訪問結束后下一個。
    @synchronized(self){
        if (nil == handle) {
            handle = [[DataHadle alloc] init];             
        }
    }
  return handle;
}

完整的單例:不僅要求我們通過方法獲取的對象是單例,如果有 對該對象進行copy mutableCopy copyWithZone 等操作

  • 完整的單例要做到四個方面:

(1).為單例對象實現(xiàn)一個靜態(tài)實例,然后設置成nil,
(2).構造方法檢查靜態(tài)實例是否為nil,是則新建并返回一個實例,
(3).重寫allocWithZone方法,用來保證其他人直接使用alloc和init試圖獲得一個新實例的時候不會產生一個新實例,
(4).適當實現(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;
  1. 重寫 allocWithZone copy mutableCopy copyWithZone

防止外界拷貝造成多個實例, 保證實例的唯一性。
注意:如果自己重寫了 allocWithZone 就不要再調用自身的 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)建一個便利構造器方法(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中應有相應的改變

// 引單例的頭文件
- (void)viewDidLoad {

      DKNightVersionManager *instance = [DKNightVersionManager sharedNightVersionManager];
      
      if (instance.type) {

       //改變成夜間模式
     } else {

       //改變成日間模式
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容