循環引用的本質是什麼?
多個對象相互都是強引用,不能釋放讓系統回收,對象A強引用對象B,對象B強引用對象C,對象C強引用對象A
iOS內存中的分區爲:棧.堆,靜態區! 棧區和靜態區是操作系統自己管理回收的,不會造成循環陰影.堆區是由程序員來控制的,在堆區中的相互引用無法回收的話就會造成循環引用
解決循環引用的方式一般是將strong改爲weak引用
weak:weak表示指向但是不擁有對象,引用計數器也不會增加,不需要手動銷燬,內存會自動銷燬
Strong:strong表示指向並且擁有對象,引用計數器增加1,引用計數器不爲0時不會銷燬,可強行將其修改爲nil進行銷燬
常見的場景就是閉包,UITabeview,Delegate,NSTimer
閉包
在copy的時候都會對block內部用到強引用的,對象A強引用對象B,對象B強引用對象C,對象C強引用對象A
在self將block作爲自己的屬性變量的時候,而在block的方法體裏面也引用了self的本身,這就很產生了一個循環已用
處理方式爲將這個self改爲弱引用
在內部調用了延時函數還使用弱指針的話會取不到該指針,因爲已經被銷燬了,需要block內部將弱指針再強引用一下
來來來,最優質的的宏定義,OMG,用它!!!
// weak obj
/#define WEAK_OBJ(type) __weak typeof(type) weak##type = type;
// strong obj
/#define STRONG_OBJ(type) __strong typeof(type) str##type = weak##type;
Delegate
在協議的代理對象都是weak來修飾的,用strong來修飾會造成循環引用
其實在開發過程中用strong(retain)並不會發現不妥,因爲功能實現就好了
在delegate屬性聲明的時候用strong
self ->aVC
BViewController *bVC = [[BViewController alloc] init];
bVC = self;
bVC.delegate引用計數器+1
aVC本身引用的BViewControllerDelagate,計數器+1
所以AViewControllerDelagate==Deleagate
該對象強行引用了,外部無法正常對其進行釋放,所以造成了循環引用
改用weak指向該對象不被強行引用,外部可以對其進行釋放