iOS ARC模式下循環(huán)引用那點事

博客地址:http://istudying.club/,小編自己搭建的博客喲??。痒钝。秉颗。

今天我們來說說循環(huán)引用。什么是循環(huán)引用送矩?當(dāng)兩個不同的對象各有一個強引用指向?qū)Ψ讲仙瑢?dǎo)致雙方的內(nèi)存都無法釋放的時候,那么循環(huán)引用就發(fā)生了栋荸。

不知道大家有沒有聽過一句話:人生就像打電話菇怀,不是你先掛,就是我先掛晌块。其實用到這里是在合適不過了爱沟。假設(shè)有兩個人打電話,彼此都強引用的對方的電話號碼匆背,但是如果雙方都不想掛電話的話呼伸,那么電話就會一直通著。在OC中也是同樣的道理钝尸,正常情況下括享,當(dāng)一個類或者對象即將釋放或者retainCount=0的時候,就會調(diào)用dealloc方法珍促,釋放相應(yīng)的內(nèi)存铃辖。但是,當(dāng)這個對象被其他對象強引用的時候猪叙,那么它就不會被回收娇斩。此時如果處理不當(dāng)?shù)脑捑蜁斐裳h(huán)引用。

首先我們先簡單的看一個循環(huán)引用的例子沐悦。首先我們在第二個控制里面成洗,聲明一個TestThreeController對象three。

@class TestThreeController;
@interface TestSecController : UIViewController
@property (nonatomic, strong) TestThreeController *three;
@end

然后在.m文件中,定義一個按鈕的點擊事件用來push藏否,并重寫dealloc方法瓶殃。

- (void)click
{
_three = [[TestThreeController alloc] init];
_three.sec = self;? // 這就是造成循環(huán)引用的代碼
[self.navigationController pushViewController:_thr animated:YES];
}
- (void)dealloc
{
NSLog(@"TestSecController - dealloc");
}

緊接著我們在第三個控制器里面聲明一個TestSecController對象的sec。

@class TestSecController;
@interface TestThreeController : UIViewController
@property (nonatomic, strong) TestSecController *sec;
@end

然后在其.m文件中重寫dealloc方法副签。

- (void)dealloc
{
NSLog(@"ThreeViewController -? dealloc");
}

正常情況下遥椿,從TestThreeController控制器pop到TestSecController的時候基矮,會執(zhí)行ThreeViewController的dealloc方法。但此時可想而知冠场,不會執(zhí)行家浇,因為循環(huán)應(yīng)用了。其實解決方法很簡單碴裙,就是將中一個屬性修飾符改成weak修飾就好了(關(guān)于strong和weak钢悲,我這里簡單說明一下,一個對象可以有多個指針共同指向舔株,假如A和B兩個Strong指針同時指向一個NSString對象”name”,當(dāng)A重新指向另一個NSString對象”word”時,此時载慈,B仍然指向”name”,如果B也指向別的對象時惭等,因為”name”此時不被任何對象所持有办铡,就會被系統(tǒng)回收辞做。如果B是weak類型的,那么當(dāng)A重指向的時候寡具,因為B是弱引用秤茅,并不持有”name”這個對象,所以”name”就會被系統(tǒng)回收)童叠。

其實OC中代理也是一樣的嫂伞,這里我就拿系統(tǒng)的tableView來舉例,我們在控制器中聲明一個@property (nonatomic, strong) UITableView *tableView的屬性拯钻,那么當(dāng)前控制器就持有了這個tableView,當(dāng)我們在給tableView設(shè)置dataSource和delegate的時候都指向self(也就是當(dāng)前的控制器)撰豺,那么tableView也就持有了當(dāng)前的控制器粪般,所以循環(huán)引用便產(chǎn)生了,現(xiàn)在大家應(yīng)該明白代理為什么用weak或者assign修飾了吧污桦。

現(xiàn)在我們來說一下blcok,相對代理而言亩歹,我個人是比較喜歡blcok的。首先解釋一下凡橱,在聲明block時為啥子用copy?因為block原本在棧區(qū)小作,那么它的生命周期由系統(tǒng)管理,如果它所屬的變量的作用域結(jié)束稼钩,那么它就被廢棄了顾稀。用copy將棧上的block復(fù)制到堆上,這樣它的生命周期就由我們手動進行管理了坝撑,當(dāng)其超過變量作用域時静秆,堆上的block還可以繼續(xù)存在粮揉。

還有一個問題,是不是OC中所有的blcok都需要我們使用copy手動將其復(fù)制到堆上抚笔?答案NO扶认,Cocoa框架中使用含有usingBlock方法名的方法,或者GCD的API中傳遞Block時殊橙,我們不需要這么做辐宾,也就是說在usingBlock和GCD中的block并不會造成循環(huán)引用。所以膨蛮,如果是我們自己聲明的block叠纹,在使用的時候,需要注意會不會造成循環(huán)引用鸽疾,而系統(tǒng)提供的block一般不會造成循環(huán)引用吊洼。

現(xiàn)在我們來說說NSTimer,這里在控制器里面,我們先聲明一個屬性

@property (nonatomic, strong) NSTimer? *timer;

然后初始化timer

_timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(run) userInfo:nil repeats:YES];

NSTimer為什么會造成循環(huán)引用呢制肮,這里我們來分析一下冒窍,首先,控制器持有NSTimer豺鼻,然后在timer初始化的時候综液,target設(shè)置為self,那么timer就持有了當(dāng)前控制器,這就造成了循環(huán)引用儒飒,所以在平時我們不使用定時器的時候谬莹,記得[_timer invalidate];并且_timer = nil;從而避免循環(huán)引用。

說起這個target桩了,我不由得想起了貌似不只有NSTimer有附帽,只有繼承UIControl的都有,于是乎井誉,我又在當(dāng)前控制器聲明了一個UIButton,并添加了addTarget,根據(jù)上面的邏輯蕉扮,這不就造成了循環(huán)引用了么。說實話颗圣,當(dāng)初我一直也想不通喳钟,于是我查閱了一下蘋果的官方文檔。

對于UIButton,說明如下

The control does not retain the object in the target parameter. It is
your responsibility to maintain a strong reference to the target object
while it is attached to a control

大致意思就是button并不會強引用這個target對象在岂,這樣一來奔则,也就不存在循環(huán)引用了。

對于NSTimer,說明如下

The object to which to send the message specified by aSelector when the
timer fires. The timer maintains a strong reference to this object until it (the
timer) is invalidated

大致意思就是timer會強引用這個target對象蔽午,直到timer執(zhí)行了invalidate方法易茬。所以,timer在使用的時候需要注意釋放的問題及老,其次NSTimer繼承NSObject并不是UIControl疾呻,所以不同情況不同對待除嘹。

好了,就說這么多了岸蜗,說的比較簡單尉咕,如果有什么不對的地方,希望留言指正璃岳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末年缎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子铃慷,更是在濱河造成了極大的恐慌单芜,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犁柜,死亡現(xiàn)場離奇詭異洲鸠,居然都是意外死亡,警方通過查閱死者的電腦和手機馋缅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門扒腕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人萤悴,你說我怎么就攤上這事瘾腰。” “怎么了覆履?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵蹋盆,是天一觀的道長。 經(jīng)常有香客問我硝全,道長栖雾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任伟众,我火速辦了婚禮岩灭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赂鲤。我一直安慰自己,他們只是感情好柱恤,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布数初。 她就那樣靜靜地躺著,像睡著了一般梗顺。 火紅的嫁衣襯著肌膚如雪泡孩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天寺谤,我揣著相機與錄音仑鸥,去河邊找鬼吮播。 笑死,一個胖子當(dāng)著我的面吹牛眼俊,可吹牛的內(nèi)容都是我干的意狠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疮胖,長吁一口氣:“原來是場噩夢啊……” “哼环戈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起澎灸,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤院塞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后性昭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拦止,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年糜颠,在試婚紗的時候發(fā)現(xiàn)自己被綠了汹族。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡括蝠,死狀恐怖鞠抑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忌警,我是刑警寧澤搁拙,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站法绵,受9級特大地震影響箕速,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜朋譬,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一盐茎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧徙赢,春花似錦字柠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枕屉,卻和暖如春常柄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工西潘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卷玉,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓喷市,卻偏偏與公主長得像相种,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子东抹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

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

  • 1.屬性readwrite蚂子,readonly,assign缭黔,retain食茎,copy,nonatomic 各是什么作...
    曾令偉閱讀 1,052評論 0 10
  • 來自網(wǎng)絡(luò) 序言 目前形勢馏谨,參加到iOS隊伍的人是越來越多别渔,甚至已經(jīng)到供過于求了。今年惧互,找過工作人可能會更深刻地體會...
    用心在飛閱讀 829評論 5 4
  • 文/Jack_lin(簡書作者)原文鏈接:http://www.reibang.com/p/5d2163640e2...
    筆筆請求閱讀 543評論 0 0
  • 序言 目前形勢哎媚,參加到iOS隊伍的人是越來越多,甚至已經(jīng)到供過于求了喊儡。今年拨与,找過工作人可能會更深刻地體會到今年的就...
    麥兜兜買兜兜閱讀 676評論 1 4
  • 目錄 屬性 修飾詞 循環(huán)引用 typeof與typedef 1. 屬性 objc所有類和對象都是c結(jié)構(gòu)體,cate...
    Ryan___閱讀 355評論 0 1