iOS 單例

概述

單例顧名思義就是只有一個(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;
}

單例模式做到這樣就完美了&

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容