iOS 單例模式

    1. 概念相關

(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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 單例模式作用 可以保證在程序運行過程中,一個類只有一個實例,而且該實例易于供外界使用 從而方便地控制了實例個數,并...
    珍此良辰閱讀 1,363評論 3 8
  • 一. 單例模式簡介 單例模式的作用可以保證在程序運行過程,一個類只有一個實例,而且該實例易于供外界訪問從而方便地控...
    xx_cc閱讀 50,273評論 15 146
  • 原鏈接:http://www.lxweimin.com/p/4867dc92337e原作者:僅供我個人收藏學習,原博...
    油菜花花花花閱讀 342評論 0 0
  • 1 單例模式 它是一種設計模式(常見的設計模式有:觀察者模式、工廠模式、門面模式等)。單例設計模式中,一個類只有一...
    歲與禾閱讀 929評論 5 9
  • 國學教育,古已有之,今又重來,復古乎,倒退乎,均不是,“溫故而知新也”。社會在發展,時代在進步,但是歷史不是...
    2dbd67f8c77a閱讀 412評論 0 0