iOS - 單例模式

weixin_34019929發表於2015-10-03

1.單例模式

  • 1.1 概念相關

(1)單例模式

在程式執行過程,一個類只有一個例項

(2)使用場合

在整個應用程式中,共享一份資源(這份資源只需要建立初始化1次)
  • 1.2 ARC實現單例

(1)步驟

01 在類的內部提供一個static修飾的全域性變數
02 提供一個類方法,方便外界訪問
03 重寫+allocWithZone方法,保證永遠都只為單例物件分配一次記憶體空間
04 嚴謹起見,重寫-copyWithZone方法和-MutableCopyWithZone方法

(2)相關程式碼

//提供一個static修飾的全域性變數,強引用著已經例項化的單例物件例項
static XMGTools *_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;
}

  • 1.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 XMGTools *_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;
}

相關文章