天天看點

matlab循環引用變量,局部變量引起的循環引用

開發中寫了個demo,具體片段如下,建立了三個局部對象Button,通過RAC做相應的按鈕事件操作。沒想到竟然發現到有記憶體洩漏的問題。因為已經排除了RAC導緻的原因(具體ReactiveCocoa的記憶體管理可以看:http://blog.csdn.net/y_csdnblog_xx/article/details/51483111),是以剛開始時候也比較一頭霧水。但是最後發現代碼中犯了一個很低級的錯誤。UIButton * btn0 = [[UIButton alloc]initWithFrame:CGRectMake(100, 450, 50, 100)];

[self.view addSubview:btn0];

UIButton * btn1 = [[UIButton alloc]initWithFrame:CGRectMake(200, 450, 50, 100)];

[self.view addSubview:btn1];[[btn0 rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton * sender) {

//do something...

btn0.selected = YES;

btn1.selected = NO;

}];[[btn1 rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(UIButton * sender) {

//do something...

btn0.selected = NO;

btn1.selected = YES;

}];

正常我們使用RAC或者Block,如果有全局屬性在Block中調用并且該Block被本類對象持有,我們都會對self做一個弱引用,更保險一些的話還會在Block中再強引用一下這個指向self的弱引用指針。這個操作就能很有效避免循環引用帶來的記憶體問題。

但是在以上代碼中,我并沒有建立全局屬性并且也沒有在Block中調用任何全局屬性,結果同樣出現了循環引用。我已經意識到了問題肯定出在Block中,就順着代碼排查可能性。我先把btn1的事件響應信号的接收Block中的btn0.selected = NO;去掉,發現問題解決了。是以意識到,即使是局部變量對象,如果存在同樣的情況,也會導緻循環引用。

具體說明:經過以上代碼,有四個地方引用了btn0對象:1.btn0指針。2.self.view。3.btn0自身事件響應信号接收方法的block。4.btn1自身事件響應信号接收方法的block。同樣有四個地方引用了btn1對象:1.btn1指針。2.self.view。3.btn1自身事件響應信号接收方法的block。4.btn0自身事件響應信号接收方法的block。這兩按鈕前三個情況都沒問題,關鍵在于第四種情況。btn0的釋放取決于btn1的釋放,btn1同樣要等btn0釋放後才可釋放其block進而才可釋放。此時就出現了循環引用。

解決辦法:給會導緻循環引用的局部對象建立弱引用指針供相應Block中使用。__weak UIButton * weakBtn0 = btn0;

__weak UIButton * weakBtn1 = btn1;