iOS單例創(chuàng)建和繼承

單例

一般來說,在iOS的工程中馆纳, 通用的tool一般都會(huì)設(shè)計(jì)成單例,這樣能保證在程序運(yùn)行過程中复亏,程序中只有一個(gè)單例對象垃你,方便數(shù)據(jù)的傳輸和處理椅文。
如果為了擴(kuò)展此單例類,希望在此基礎(chǔ)上增加面向各模塊專用的單例方法惜颇,該如何處理呢皆刺。
可以采用的方法有兩種:

  • 分類:可以針對各個(gè)模塊創(chuàng)建對應(yīng)的分類,并添加方法凌摄。缺點(diǎn)是不能繼承原有單例的屬性羡蛾。
  • 繼承:也可以針對各個(gè)模塊創(chuàng)建出對應(yīng)的子類,并添加方法锨亏。也可以繼承父類的屬性痴怨。

繼承單例遇到的問題

因?yàn)閱卫龑ο笤诔绦蛑兄粫?huì)創(chuàng)建一次,創(chuàng)建成功后再次訪問單例對象器予,訪問的是同一個(gè)對象浪藻,故子類如果采用父類的方法進(jìn)行創(chuàng)建的話,訪問的對象還是父類乾翔,子類添加的屬性和方法將會(huì)無法訪問而造成crash爱葵。

    // 父類
    QYSingleton *singleton = [QYSingleton shareSingleton];
    NSLog(@"%@ - %p", singleton, singleton);
    // 方法
    [singleton run];

打印結(jié)果

    單例繼承[3651:162046] name: father, age: 30, sex: male - 0x604000221da0
    單例繼承[3711:165295] QYSingleton run

    // 子類
    // 子類:采用繼承的父類的類方法進(jìn)行創(chuàng)建
    QYSubSingleton *subSingleton = [QYSubSingleton shareSingleton];
    NSLog(@"%@ - %p", subSingleton, subSingleton);

打印結(jié)果

    name: father, age: 30, sex: male - 0x604000221da0

由以上結(jié)果可知,這兩個(gè)對象的地址是一樣的,也證明了程序中只會(huì)創(chuàng)建一份單例對象萌丈。

  • 給子類對象添加屬性暇韧,因創(chuàng)建出來的對象為父類對象,故-[QYSingleton setHobby:]: unrecognized selector sent to instance 0x60400002b8a0找不到屬性對應(yīng)的settercrash.
  • 給子類對象添加方法浓瞪,同樣的會(huì)-[QYSingleton walk]: unrecognized selector sent to instance 0x6000002212e0

子類的創(chuàng)建方法

  • 通過alloc懈玻、init進(jìn)行創(chuàng)建
    // 父類
    QYSingleton *singleton = [QYSingleton shareSingleton];
    NSLog(@"%@ - %p", singleton, singleton);
    // 方法
    [singleton run];

    // 打印結(jié)果
    單例繼承[6181:308541] name: father, age: 30, sex: male - 0x6040000349e0
    單例繼承[6220:310333] QYSingleton run
    // 通過alloc、init進(jìn)行創(chuàng)建
    QYSubSingleton *subSingleton = [[QYSubSingleton alloc] init];
    // 繼承的屬性
    subSingleton.name = @"subObject";
    // 子類添加的屬性
    subSingleton.hobby = @"游泳";
    NSLog(@"%@ - %p", subSingleton, subSingleton);

    // 繼承的方法
    [subSingleton run];
    // 添加的方法
    [subSingleton walk];

    // 打印的結(jié)果
    單例繼承[6220:310333] name: subObject, age: 30, sex: male, hobby:游泳 - 0x60000025ad90
    // 調(diào)用父類的方法
    單例繼承[6220:310333] QYSubSingleton run
    // 子類添加的方法
    單例繼承[6220:310333] QYSubSingleton walk

由打印可知乾颁,這樣才能創(chuàng)建出新的子類對象涂乌,并且可以更改父類的初始屬性,添加新的屬性和方法

  • 給子類添加單例的方法進(jìn)行創(chuàng)建
  • 方法:+ (instancetype)shareSubSingle;
  • 使用:QYSubSingleton *subSingleton = [QYSubSingleton shareSubSingle];
  • 驗(yàn)證:將alloc英岭、init替換為shareSubSingle創(chuàng)建子類對象進(jìn)行驗(yàn)證
  • 結(jié)論:經(jīng)驗(yàn)證湾盒,這樣也能創(chuàng)建出新的子類對象,并能添加屬性和方法

更嚴(yán)謹(jǐn)?shù)膭?chuàng)建單例的方式

以上創(chuàng)建單例和單例的子類都不是很嚴(yán)謹(jǐn)诅妹,父類通過shareSingleton創(chuàng)建的對象罚勾,和通過alloc、init創(chuàng)建的對象是不一樣的吭狡。
這是因?yàn)榧庋辏琌C通過allocWithZone:這個(gè)方法來申請內(nèi)存的,故我們要覆寫這個(gè)方法划煮,保證創(chuàng)建出來的對象是唯一的送丰。

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

修改shareSingleton為:

+ (instancetype)shareSingleton {
    static dispatch_once_t onceToken;
    static QYSingleton *singleton = nil;
    dispatch_once(&onceToken, ^{
        singleton = [[super allocWithZone:NULL] init];
    });
    return singleton;
}

這樣就不管是使用什么方法,創(chuàng)建出來的對象就都是唯一的了弛秋。

創(chuàng)建繼承的單例

因?yàn)閱卫哂形ㄒ恍云黪铮WC每個(gè)創(chuàng)建的類是不同的,所以在每個(gè)類生成時(shí)蟹略,我們動(dòng)態(tài)的給類綁定唯一的對象登失。
使用runTime的關(guān)聯(lián)對象進(jìn)行創(chuàng)建。
如下:

/** 單例對象 */
+ (instancetype)shareObject {
    // 獲取當(dāng)前對象的類
    Class selfClass = [self class];
    // 從類中獲取對象
    id instance = objc_getAssociatedObject(selfClass, @"shareObject");
    if (!instance) {
        // 不存在挖炬,創(chuàng)建對象
        instance = [[super allocWithZone:NULL] init];
        // 給類綁定對象
        objc_setAssociatedObject(selfClass, @"shareObject", instance, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return instance;
}

/** 保證alloc揽浙、init也創(chuàng)建同樣的對象 */
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    // 獲取當(dāng)前對象的類
    Class class = [self class];
    // 返回當(dāng)前類綁定的對象
    return [class shareObject];
}

驗(yàn)證:

    QYObject *objc = [QYObject shareObject];
    NSLog(@"%p", objc);
    
    QYObject *objc2 = [[QYObject alloc] init];
    NSLog(@"%p", objc2);
    
    QYSubObject *subObjc = [QYSubObject shareObject];
    NSLog(@"%p", subObjc);
    
    QYSubObject *subObjc2 = [[QYSubObject alloc] init];
    NSLog(@"%p", subObjc2);

結(jié)果:

2018-09-12 09:43:22.764627+0800 單例繼承[1639:49824] 0x6040000030d0
2018-09-12 09:43:22.764815+0800 單例繼承[1639:49824] 0x6040000030d0
2018-09-12 09:43:22.764953+0800 單例繼承[1639:49824] 0x604000002d90
2018-09-12 09:43:22.765140+0800 單例繼承[1639:49824] 0x604000002d90

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茅茂,隨后出現(xiàn)的幾起案子捏萍,更是在濱河造成了極大的恐慌,老刑警劉巖空闲,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件令杈,死亡現(xiàn)場離奇詭異,居然都是意外死亡碴倾,警方通過查閱死者的電腦和手機(jī)逗噩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門掉丽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人异雁,你說我怎么就攤上這事捶障。” “怎么了纲刀?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵项炼,是天一觀的道長。 經(jīng)常有香客問我示绊,道長锭部,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任面褐,我火速辦了婚禮拌禾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘展哭。我一直安慰自己湃窍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布匪傍。 她就那樣靜靜地躺著您市,像睡著了一般。 火紅的嫁衣襯著肌膚如雪析恢。 梳的紋絲不亂的頭發(fā)上墨坚,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音映挂,去河邊找鬼。 笑死盗尸,一個(gè)胖子當(dāng)著我的面吹牛柑船,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泼各,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼鞍时,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扣蜻?” 一聲冷哼從身側(cè)響起逆巍,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莽使,沒想到半個(gè)月后锐极,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芳肌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年灵再,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肋层。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翎迁,死狀恐怖栋猖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情汪榔,我是刑警寧澤蒲拉,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站痴腌,受9級特大地震影響全陨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衷掷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一辱姨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧戚嗅,春花似錦雨涛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至躏尉,卻和暖如春蚯根,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胀糜。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工颅拦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人教藻。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓距帅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親括堤。 傳聞我的和親對象是個(gè)殘疾皇子碌秸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

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

  • 現(xiàn)在的人啊讥电,好像都很著急。 遇上對的人著急去愛轧抗,感覺不對了又著急去恨恩敌, 于是,很多人都倉促的分道揚(yáng)鑣了鸦致。 平靜了一...
    一個(gè)人的劇場閱讀 902評論 0 1
  • 所謂溝通就是同步潮剪。每個(gè)人都有獨(dú)特地方涣楷,而與人交際則要求他與別人一致】古觯——卡耐基狮斗。 盡管不怎么喜歡卡耐基的成功學(xué),但...
    聞知閱讀 913評論 0 0
  • 今天寶爸打電話二寶有點(diǎn)發(fā)燒弧蝇,感覺挺對不起寶寶們碳褒,整天忙這忙那,尤其是這個(gè)暑假就沒在家呆幾天看疗,回家來姐妹倆都往跟前湊...
    fba947bf0ca5閱讀 151評論 0 1
  • 我的領(lǐng)導(dǎo)是一個(gè)直性格的美女沙峻,她秉承著有啥就說啥的原則。 過一段時(shí)間就會(huì)把我單獨(dú)叫出去談?wù)勗捔椒迹o我提意見摔寨,說出我在工...
    羊羊羊羊羊陽閱讀 302評論 1 0