今天面試問(wèn)道了循環(huán)引用,所以就看了看,原來(lái)只是知道使用了Block容易造成循環(huán)引用。今天就來(lái)簡(jiǎn)單的介紹一些循環(huán)引用。
先來(lái)簡(jiǎn)單介紹一下什么是循環(huán)引用?
循環(huán)引用可以簡(jiǎn)單的理解成:A對(duì)象引用了B對(duì)象,B對(duì)象又引用了A對(duì)象。兩者相互保持對(duì)方的一個(gè)引用。導(dǎo)致任何時(shí)候計(jì)數(shù)都不為0,最終兩者都無(wú)法釋放。
產(chǎn)生循環(huán)引用的方式:
1、NSTimer
比如說(shuō)我在一個(gè)類(lèi)中聲明了一個(gè)NSTimer計(jì)時(shí)器類(lèi)。而在NSTimer 的方法
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
當(dāng)我們?cè)赼Selector中調(diào)用了自己的屬性或者方法時(shí)(比如調(diào)用了自己的self.class),那么當(dāng)我們實(shí)例化這個(gè)類(lèi)之后然后我們讓他延遲幾秒釋放,那么我們會(huì)發(fā)現(xiàn)time中的aSelector會(huì)一直執(zhí)行。現(xiàn)在就來(lái)簡(jiǎn)單的分析一下吧:
timer沒(méi)有調(diào)用invalidate方法是不會(huì)因?yàn)轭?lèi)的釋放而停止的。而對(duì)于類(lèi)實(shí)例來(lái)說(shuō):它認(rèn)為timer沒(méi)有執(zhí)行完畢,所以沒(méi)有機(jī)會(huì)進(jìn)入dealloc。循環(huán)引用,相互等待。所以我們可以在類(lèi)實(shí)例釋放之前手動(dòng)調(diào)用一下NSTimer的invalidate方法。還有就是下面的代碼:
__weak ClassA *weakSelf = self;timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:weakSelf selector:@selector(startTimer) userInfo:nil repeats:YES];
所以我們?cè)谑褂肗STimer時(shí)一定要注意NSTimer的invalidate時(shí)機(jī)。
2、Block
例如我們定義了一個(gè)block塊,然后作為了一個(gè)類(lèi)的屬性變量,那么當(dāng)我們?cè)谶@個(gè)塊中調(diào)用自己的屬性或者方法的時(shí)候就會(huì)產(chǎn)生循環(huán)引用。
解決循環(huán)引用方法:通過(guò)__weak聲明一個(gè)self的新變量來(lái)代替原來(lái)的self。這樣在塊中可以通過(guò)這個(gè)弱引用self來(lái)防止block中對(duì)self進(jìn)行strong引用。
3、delegate
一般情況下我們聲明delegate時(shí)使用assign賦值,因?yàn)橘x值屬性不會(huì)增加計(jì)數(shù)。
如果一個(gè)UITableViewController 對(duì)象a通過(guò)retain獲取了UITableView對(duì)象b的所有權(quán),這個(gè)UITableView對(duì)象b的delegate又是a, 如果這個(gè)delegate是retain方式的,那基本上就沒(méi)有機(jī)會(huì)釋放這兩個(gè)對(duì)象了。
先簡(jiǎn)單的介紹這么多,因?yàn)檫@邊沒(méi)有電腦,也不太方便進(jìn)行例子演示。有電腦了再補(bǔ)上去。這里先做一下記錄。
------------------------------------------------------------------------------------結(jié)束------------------------------------------------------------------------------------
也很感謝哪位大神能夠附上一些例子。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注