ios — 單例使用

一直想花時間把之前項目常用的控件及功能整理出來像棘,本打算把AFNetworking二次封裝下施掏,想到需要使用單例來封裝AFHTTPSessionManager類鄙麦,看到很多使用單例的方法處理不夠嚴謹应媚,這里還是單獨拎出來,把單例的用法講一下缺猛。

知識點

1.alloc int 的功能及調(diào)用順序
2.allocWithZone 的調(diào)用
3.單列的實現(xiàn)原理及正確使用

1.alloc init 的使用
我們通常創(chuàng)建一個oc對象的時候,一般都是使用alloc init方法椭符。

alloc   給對象分配內(nèi)存空間
init    初始化該對象

我們通常會這么創(chuàng)建對象

 person * p1 = [[person alloc]init];

這樣操作荔燎,就完成一個對象的創(chuàng)建過程。
那么系統(tǒng)在什么時候給對象分配內(nèi)存空間呢销钝?其實當我們執(zhí)行alloc方法的時候有咨,系統(tǒng)會自動調(diào)用他如下方法來為對象分配內(nèi)存地址

+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");

我們點擊進去可以查看到


系統(tǒng)方法.png

這是NSObject的方法,也就是只要是oc對象蒸健,都擁有此方法座享。
其實創(chuàng)建對象,也就是創(chuàng)建一個類型的指針似忧,創(chuàng)建的時候分配內(nèi)存地址渣叛。

 person * p1 = [[person alloc]init];//執(zhí)行順序如下
// 1.alloc
// 2.+ (instancetype)allocWithZone
// 3.init

還是看代碼來驗證
我們創(chuàng)建一個常用的person類

#import "person.h"

@implementation person

 //調(diào)用順序 如下
 -(instancetype)init{
     if (self = [super init])// 3
     {
     
     }
     return self;// 4
 }
 +(instancetype)allocWithZone:(struct _NSZone *)zone
 {
     static person *person = nil;
     person = [super allocWithZone:zone];//  1
     return person;// 2
 }

在外部調(diào)用

person * p1 = [[person alloc]init];

編譯項目,看行執(zhí)行順序


alloc順序.gif

編譯順序盯捌,如上注釋诗箍。
我們來創(chuàng)建三個person對象

 person * p1 = [[person alloc]init];
 person * p2 = [[person alloc]init];
 person * p3 = [[person alloc]init];
 NSLog(@"%@ \n %@ \n %@",p1,p2,p3);

打印內(nèi)存地址

<person: 0x60000001fa90>
<person: 0x60000001fb60>
<person: 0x60000001fb50>

每次創(chuàng)建對象,都會分配新的內(nèi)存地址。其實創(chuàng)建oc對象的就是創(chuàng)建了一個對象類型的指針滤祖,分配內(nèi)存地址筷狼,之后讓指針指向自己的內(nèi)存控件,之后再init方法實現(xiàn)對對象的初始化匠童,擁有調(diào)用自己屬性和方法的權利埂材。

單例使用常用方法

單例是在整個工程中只擁有一個該類實例。
1.單例使用
我們來看下汤求,我們通常創(chuàng)建單例的方法

 +(instancetype)sharedInstance;
 {
     static person *single = nil;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     single =[[self alloc]init];
     });
     return single;
 }

這里俏险,我們使用GCD提供的dispatch_once的方法,在這個方法內(nèi)部使用創(chuàng)建對象的[[self alloc]init]方法扬绪,保證這個方法只執(zhí)行一遍竖独。
我們創(chuàng)建單列如下

 person * p4 = [person sharedInstance];
 person * p5 = [person sharedInstance];
 person * p6 = [person sharedInstance];
 NSLog(@"%@ \n %@ \n %@",p4,p5,p6);

打印內(nèi)存地址如下

<person: 0x60c00000cc00>
<person: 0x60c00000cc00>
<person: 0x60c00000cc00>

通過驗證,的確返回的同一個實例挤牛,我們的目標達到了莹痢?

問題

可是如果還是用以下方法,還會返回同一個實例對象嘛

person * p1 = [[person alloc]init];

我們來驗證下

person * p1 = [[person alloc]init];
person * p2 = [[person alloc]init];
person * p3 = [[person alloc]init];
NSLog(@"%@ \n %@ \n %@",p1,p2,p3);

person * p4 = [person sharedInstance];
person * p5 = [person sharedInstance];
person * p6 = [person sharedInstance];
NSLog(@"%@ \n %@ \n %@",p4,p5,p6);

打印內(nèi)存地址如下

<person: 0x60000001fa90>
<person: 0x60000001fb60>
<person: 0x60000001fb50>
<person: 0x60c00000cc00>
<person: 0x60c00000cc00>
<person: 0x60c00000cc00>

可見通過alloc init方法創(chuàng)建的對象墓赴,還是分配的不同的內(nèi)存空間竞膳。
我們該怎么避免這樣的現(xiàn)象發(fā)生呢?

單例使用完善

這里我們重寫系統(tǒng)創(chuàng)建對象時分配內(nèi)存地址的方法诫硕,并把創(chuàng)建單例方法寫在此方法中坦辟,保證每次創(chuàng)建對象都返回同一個內(nèi)存空間

// 把創(chuàng)建單例的寫法寫在系統(tǒng)為對象分配內(nèi)存地址的方法中
 +(instancetype)allocWithZone:(struct _NSZone *)zone
 {
     static person * single = nil;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
     single = [super allocWithZone:zone];// 最先執(zhí)行,只執(zhí)行一次
     });
     return single;
 }

使用方法如下

// sharedInstance方法中章办,返回的是[[self alloc]init]方法返回的實例
 +(instancetype)sharedInstance
 {
   return [[self alloc]init];// 這里會調(diào)用init方法
 }
// init方法锉走,重寫init方法
 -(instancetype)init
 {
    if (self = [super init]) {

 }
    return self;
 }
// 把創(chuàng)建單例的寫法寫在系統(tǒng)為對象分配內(nèi)存地址的方法中
 +(instancetype)allocWithZone:(struct _NSZone *)zone
 {
     static person * single = nil;
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
    // 記住這里只會執(zhí)行一次
     single = [super allocWithZone:zone];// 最先執(zhí)行,只執(zhí)行一次
     });
     return single;
 }

通過代碼來驗證下

person * p1 = [[person alloc]init];
person * p2 = [[person alloc]init];
person * p3 = [[person alloc]init];
NSLog(@"%@ \n %@ \n %@",p1,p2,p3);

person * p4 = [person sharedInstance];
person * p5 = [person sharedInstance];
person * p6 = [person sharedInstance];
NSLog(@"%@ \n %@ \n %@",p4,p5,p6);
    
<person: 0x60800000a3e0>
<person: 0x60800000a3e0>
<person: 0x60800000a3e0>
<person: 0x60800000a3e0>
<person: 0x60800000a3e0>
<person: 0x60800000a3e0>

返回來了同一個實例藕届,不管用alloc init創(chuàng)建還是直接用sharedInstance這個方法挪蹭。
這樣的創(chuàng)建方法,比我們文中提到的常用創(chuàng)建的單例方法更完善翰舌。
[end]

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嚣潜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子椅贱,更是在濱河造成了極大的恐慌懂算,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庇麦,死亡現(xiàn)場離奇詭異计技,居然都是意外死亡,警方通過查閱死者的電腦和手機山橄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門垮媒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事睡雇∶瘸模” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵它抱,是天一觀的道長秕豫。 經(jīng)常有香客問我,道長观蓄,這世上最難降的妖魔是什么混移? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮侮穿,結果婚禮上歌径,老公的妹妹穿的比我還像新娘。我一直安慰自己亲茅,他們只是感情好回铛,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芯急,像睡著了一般勺届。 火紅的嫁衣襯著肌膚如雪驶俊。 梳的紋絲不亂的頭發(fā)上娶耍,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音饼酿,去河邊找鬼榕酒。 笑死,一個胖子當著我的面吹牛故俐,可吹牛的內(nèi)容都是我干的想鹰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼药版,長吁一口氣:“原來是場噩夢啊……” “哼辑舷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起槽片,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤何缓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后还栓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碌廓,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年剩盒,在試婚紗的時候發(fā)現(xiàn)自己被綠了谷婆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纪挎,靈堂內(nèi)的尸體忽然破棺而出期贫,到底是詐尸還是另有隱情,我是刑警寧澤异袄,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布唯灵,位于F島的核電站,受9級特大地震影響隙轻,放射性物質(zhì)發(fā)生泄漏埠帕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一玖绿、第九天 我趴在偏房一處隱蔽的房頂上張望敛瓷。 院中可真熱鬧,春花似錦斑匪、人聲如沸呐籽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狡蝶。三九已至,卻和暖如春贮勃,著一層夾襖步出監(jiān)牢的瞬間贪惹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工寂嘉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奏瞬,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓泉孩,卻偏偏與公主長得像硼端,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子寓搬,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

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