循環引用的本質是什麼?
多個對象互相都是強引用,不能釋放讓系統回收,對象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指向該對象不被強行引用,外部可以對其進行釋放