單例在開發(fā)過程中贯要,幾乎所有的項目都會用到霹菊。當然想讓一個對象在整個運行的過程中的地址只使用一個的方法有很多镰官。比如在AppDelegate中提供一個只讀屬性提前, 僅僅在.m文件中創(chuàng)建一次, 那么這個對象在整個運行中也能保證只是一個地址。但是這種方式也太屌絲了泳唠, 接下來還是來談談我們所耳熟能詳?shù)膯卫O計吧狈网。
相信,很多人都說一個單例的設計很簡單笨腥,一直使用了多年的代碼也沒有出現(xiàn)過什么問題孙援。不管怎么樣,盡然進來了扇雕, 就看看我的設計歷程吧拓售。。镶奉。础淤。。哨苛。
1鸽凶、創(chuàng)建一個單例類
一個干凈利落的類叫SingleObject。然后首當其沖的將單例方法實現(xiàn)了建峭,整體代碼如下:
.h文件
#import?@interface?SingleObject?:?NSObject
/**
?單例類方法
?@return?返回一個共享對象
?*/
+?(instancetype)sharedInstance;
//?姓名
@property?(nonatomic,?copy)?NSString*?name;
@end
.m文件
#import?"SingleObject.h"
@implementation?SingleObject
static?SingleObject*?kSingleObject?=?nil;
/**?單例類方法?*/
+?(instancetype)sharedInstance?{
????static?dispatch_once_t?onceToken;
????dispatch_once(&onceToken,?^{
????????kSingleObject?=?[[self?allocWithZone:NULL]?init];
????});
????return?kSingleObject;
}
@end
OK, 一個單例的類這樣就OK了玻侥,這是我的實驗結(jié)果:
事實證明,不管調(diào)用多少次+ sharedInstance方法亿蒸, 返回的都是一個對象凑兰。
2、allocWithZone:出場
又作了一個實驗:
厲害了边锁,我的鍋姑食。還是不行,萬一有小朋友像我一樣不按照套路出場茅坛, 直接調(diào)用alloc來創(chuàng)建對象音半, 那么不就又創(chuàng)建一個對象空間么?于是想到了allocWithZone:方法贡蓖, 于是這樣就被重寫了:
于是曹鸠,再看看剛剛剛的那時出錯實驗:
厲害了,我的鍋斥铺,這次錯得更離譜了彻桃。原因是這個:
于是,就修改一下吧仅父,這樣子試試:
這一次叛薯,又對了浑吟。
然后笙纤,由這樣的實驗了一下:
盡然so01為空耗溜, 靜靜想想也是合理的, 畢竟第一次直接調(diào)用alloc執(zhí)行allocWithZone:的時候省容,kSingleObject根本就沒有值抖拴。
那就這樣實現(xiàn)以下吧:
再次實驗一下:
嗯, 結(jié)果很對!其實到這里就差不多了腥椒,先靜下來說點其它的吧阿宅。
對于一個碼農(nóng)來說,很多的時候只要是結(jié)果對了笼蛛,其它的都是小事洒放。就像上面的這一系列的實現(xiàn)一樣,從某種意義上來說allocWithZone:方法滨砍,完全沒有必要去實現(xiàn)往湿,直接只用 + sharedInstance 不就行了么?惋戏!這樣的話领追,代碼還很簡潔。通常一個單例响逢,誰還會想著去直接去調(diào)用alloc來創(chuàng)建對象呢绒窑。確實是這樣的,如果我在使用單例的時候舔亭,直接去調(diào)用alloc來創(chuàng)建對象些膨,我自己都感覺到很屌絲。但是钦铺,話又說回來傀蓉,有的時候難免也需要裝一下逼,對于程序員來說职抡,一天除了裝逼葬燎,還有什么可以用來娛樂的呢?缚甩!
伙計們谱净、為了更全面的裝逼,接下來又要有新問題了擅威。
在OC中除了alloc能全新的創(chuàng)建一個地址空間外,還有其它的系統(tǒng)方法:+ new壕探,copy與mutableCopy。
3郊丛、到new出場了
第一個問題是:在上面實現(xiàn)的前提下李请,如果直接調(diào)用new來創(chuàng)建對象的話瞧筛,會有出現(xiàn)新的bug么,看看這個實驗:
看上去很對的樣子导盅。[偷笑中]
的確较幌, 這個系統(tǒng)類方法是不需要重寫的。好像應該可能肯定這個方法的內(nèi)部是調(diào)用了+alloc白翻、-init這兩個方法乍炉。
所以,在以后看到別人的單例中重寫了這個方法的話滤馍,你懂的岛琼,默默的笑一會兒就可以了。[得意中]
4巢株、輪copy與mutableCopy出場
有一個常識:在OC中的槐瑞,除了一些特別的類是系統(tǒng)已經(jīng)支持copy與mutableCopy的,其它的類是需要開發(fā)者自己遵守NSCopying與NSMutableCopying這兩個協(xié)議阁苞,然后實現(xiàn)其協(xié)議方法來支持copy與mutableCopy方法的困檩。如果沒有實現(xiàn)這兩個協(xié)議方法的話,直接調(diào)用copy或者mutableCopy方法是會直接crash的猬错,即使這兩個方法是在NSObject中公開的窗看。
對于一個單例來說,是沒有必要去實現(xiàn)這兩個方法的功能倦炒,但是為了代碼的嚴謹性显沈,不對、應該說是為了裝逼逢唤。也需要去考慮一下拉讯,如果別人調(diào)用了這兩個方法的情況。
所以有了這個下面的代碼:
然后,到了這里有的小伙伴心中又不好受了鳖藕,說應該是這樣來寫:
其實魔慷,我想說這個也是對的,沒有問題著恩,但是我個人感覺沒有必要院尔。然后又有一個小伙伴說:“萬一kSingleObject的值為空, 怎么辦喉誊?”邀摆,這個問題確實是難倒我了,因為我不知道一個單例的對象調(diào)用copy或者mutableCopy方法伍茄, 是怎么做到kSingleObject還是為空的栋盹??敷矫?例获?汉额??榨汤?蠕搜?如果調(diào)用了copy或者mutableCopy方法,kSingleObject還是為空件余,只能說明這個單例設計本身就有問題讥脐, 但是設計的這個單例本身是沒有問題的嘛遭居。[偷笑中]
整個設計歷程啼器,終于結(jié)束了,公布收官俱萍。又有一個小伙伴不服氣起來端壳,怎么就結(jié)束了,NSCopying與NSMutableCopying這兩個協(xié)議還沒有見到呢枪蘑?兩個協(xié)議方法也沒有實現(xiàn)损谦。厲害了,我的鍋岳颇。我就很納悶了照捡,這兩個協(xié)議需要實現(xiàn)么?當說出不需要實現(xiàn)话侧, 像上面重寫一下copy與mutableCopy就可以了栗精。話還沒有落下,又有一個小伙伴又來事了瞻鹏,說:“別人設計的都重寫了NSCopying與NSMutableCopying協(xié)議方法的悲立,還調(diào)用了+ sharedInstance方法”。剛果不是說了么新博,單例是不應該支持copy與mutableCopy操作的薪夕。重寫了copy與mutableCopy方法,就可以了赫悄。
到這里原献, 就真的要收官了。
發(fā)布中...
發(fā)布中...
發(fā)布中...
發(fā)布中...
發(fā)布中...
發(fā)布中...
突然又想起埂淮,盡然要裝逼姑隅,為什么不裝得更全面一點呢?還有一個ARC與MRC的事情同诫。
5粤策、MRC出場
是的,在OC中有一個MRC的東西误窖。MRC這東西很重要叮盘,但是我開發(fā)這些年很少用到秩贰,但是理解她與分析她還是可以的。想當年柔吼,我也能給臺下的16個大神在講臺之上分析這個個retainCount值的來龍去脈毒费。這里就不詳細介紹了,感興趣的自學吧愈魏,網(wǎng)上大神資料不少觅玻。
具體的加上這幾句代碼: