iOS之單例寫法

這是我之前不嚴謹?shù)膭?chuàng)建單例的寫法
.h

@interface MySingle : NSObject
+ (instancetype)shareInstance; 
@end

.m

+ (instancetype)shareInstance
{
    static MySingle *_mySingle = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _mySingle = [[MySingle alloc] init];
    });
    return _mySingle;
}

這種寫法有問題呀,雖然只提供了一種初始化方式斧散,但你不能阻止別人用 [[xxx alloc] init],初始化呀。
下面是測試的例子

    MySingle *single01 = [MySingle shareInstance];
    NSLog(@"single 01 = %@",single01);
    
    MySingle *single02 = [MySingle shareInstance];
    NSLog(@"single 02 = %@",single02);
    
    MySingle *single03 = [[MySingle alloc] init];
    NSLog(@"single 03 = %@",single03);
輸出
2018-01-08 16:16:42.844100+0800 單例測試[6605:444452] single 01 = <MySingle: 0x60400020b1a0>
2018-01-08 16:16:42.844310+0800 單例測試[6605:444452] single 02 = <MySingle: 0x60400020b1a0>
2018-01-08 16:16:42.844815+0800 單例測試[6605:444452] single 03 = <MySingle: 0x60400020b2e0>

通過上面的測試,可以看到通過shareInstance方法獲取的對象是相同的菠红,但是用allocinit構(gòu)造對象時律杠,得到的對象卻是不一樣的潭流。
通過不同的方式獲得不同的對象,是有問題的柜去,所以要封鎖初始化的方式灰嫉,如alloc copy mutableCopy 還有一個new
下面是我摘抄的原理哈

創(chuàng)建對象的步驟分為申請內(nèi)存(alloc)、初始化(init)這兩個步驟嗓奢,我們要確保對象的唯一性讼撒,因此在第一步這個階段我們就要攔截它。當我們調(diào)用alloc方法時股耽,OC內(nèi)部會調(diào)用allocWithZone這個方法來申請內(nèi)存根盒,我們覆寫這個方法,然后在這個方法中調(diào)用shareInstance方法返回單例對象物蝙,這樣就可以達到我們的目的炎滞。拷貝對象也是同樣的原理诬乞,覆寫copyWithZone方法册赛,然后在這個方法中調(diào)用shareInstance方法返回單例對象
下面是改良后的代碼
MySingle2

#import "MySingle2.h"

@implementation MySingle2
+(instancetype)shareInstance
{
    static MySingle2 *_mySingle = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _mySingle = [[super allocWithZone:NULL] init];
    });
    return _mySingle;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    return [self shareInstance];
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    return self;
}

再放上測試代碼

    MySingle2 *single01 = [MySingle2 shareInstance];
    NSLog(@"single 01 = %@",single01);
    
    MySingle2 *single02 = [MySingle2 shareInstance];
    NSLog(@"single 02 = %@",single02);
    
    MySingle2 *single03 = [[MySingle2 alloc] init];
    NSLog(@"single 03 = %@",single03);
    
    NSLog(@"copy = %@",[single03 copy]);
    
    MySingle2 *single04 = [MySingle2 new];
    NSLog(@"new  = %@",single04);

輸出

//    2018-01-08 16:56:26.973122+0800 單例測試[7195:493942] single 01 = <MySingle2: 0x604000017360>
//    2018-01-08 16:56:26.973357+0800 單例測試[7195:493942] single 02 = <MySingle2: 0x604000017360>
//    2018-01-08 16:56:26.973630+0800 單例測試[7195:493942] single 03 = <MySingle2: 0x604000017360>
//    2018-01-08 16:56:26.973808+0800 單例測試[7195:493942] copy = <MySingle2: 0x604000017360>
//    2018-01-08 16:56:26.973952+0800 單例測試[7195:493942] new  = <MySingle2: 0x604000017360>

ok 不管用哪種方式 初始化 獲得的對象都是一樣的,這樣就達到我們單例的目的了丽惭。
你以為到這就結(jié)束了击奶,嘿嘿,且看下面
做一點小修改

#import "MySingle3.h"

@implementation MySingle3

 static MySingle3 *_mySingle = nil;
+(instancetype)shareInstance
{
    if (_mySingle == nil) {
        _mySingle = [[MySingle3 alloc] init];
    }
    return _mySingle;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _mySingle = [super allocWithZone:zone];
    });
    return _mySingle;
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
    return self;
}
@end

下面的寫法我感覺比較自然點责掏,就是換了一個樣子初始化柜砾。
有沒有發(fā)現(xiàn),如果寫單例换衬,都要寫這么一堆代碼痰驱,豈不是很繁瑣。
可以寫成宏的方式瞳浦,寫成一個文件担映,直接調(diào)用,即可叫潦。
廢話不多說了蝇完,直接上代碼
這是調(diào)用方式
.h

#import <Foundation/Foundation.h>
#import "Single.h"

@interface MySingle4 : NSObject
SingleInterface(MySingle4);
@end

.m

@implementation MySingle4
SingleImplementation(MySingle4);
@end

好吧,再把測試代碼也貼出來

    MySingle4 *single01 = [MySingle4 shareMySingle4];;
    NSLog(@"single 01 = %@",single01);
    
    MySingle4 *single02 = [MySingle4 shareMySingle4];
    NSLog(@"single 02 = %@",single02);
    
    MySingle4 *single03 = [[MySingle4 alloc] init];
    NSLog(@"single 03 = %@",single03);
    
    NSLog(@"copy = %@",[single03 copy]);
    
    MySingle4 *single04 = [MySingle4 new];
    NSLog(@"new  = %@",single04);

輸出

2018-01-08 17:31:56.844532+0800 單例測試[7726:530743] single 01 = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.844795+0800 單例測試[7726:530743] single 02 = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.845013+0800 單例測試[7726:530743] single 03 = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.845225+0800 單例測試[7726:530743] copy = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.845471+0800 單例測試[7726:530743] new  = <MySingle4: 0x600000009b00>

傳送門

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市短蜕,隨后出現(xiàn)的幾起案子氢架,更是在濱河造成了極大的恐慌,老刑警劉巖朋魔,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岖研,死亡現(xiàn)場離奇詭異,居然都是意外死亡警检,警方通過查閱死者的電腦和手機孙援,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扇雕,“玉大人拓售,你說我怎么就攤上這事⊥菘悖” “怎么了邻辉?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長腮鞍。 經(jīng)常有香客問我值骇,道長,這世上最難降的妖魔是什么移国? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任吱瘩,我火速辦了婚禮,結(jié)果婚禮上迹缀,老公的妹妹穿的比我還像新娘使碾。我一直安慰自己,他們只是感情好祝懂,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布票摇。 她就那樣靜靜地躺著,像睡著了一般砚蓬。 火紅的嫁衣襯著肌膚如雪矢门。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天灰蛙,我揣著相機與錄音祟剔,去河邊找鬼。 笑死摩梧,一個胖子當著我的面吹牛物延,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仅父,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼叛薯,長吁一口氣:“原來是場噩夢啊……” “哼浑吟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起案训,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤买置,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后强霎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蓉冈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年城舞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寞酿。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡家夺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伐弹,到底是詐尸還是另有隱情拉馋,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布惨好,位于F島的核電站煌茴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏日川。R本人自食惡果不足惜蔓腐,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望龄句。 院中可真熱鬧回论,春花似錦、人聲如沸分歇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽职抡。三九已至葬燎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間繁调,已是汗流浹背萨蚕。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蹄胰,地道東北人岳遥。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像裕寨,于是被迫代替她去往敵國和親浩蓉。 傳聞我的和親對象是個殘疾皇子派继,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容