內存的循環引用swift
在 ARC,開發者將會定義一個變量爲「strong」或「weak」。一個 weak 弱引用沒法 retain 對象,而 strong 引用會 retain 這個對象,並將其引用計數加一。安全
循環引用就是指兩個對象互相retain對方,經過OBJC的release是沒法銷燬這兩個對象的app
更嚴重的是,若是幾個對象間接相互引用,好比a<-b b<-c c<-a 那麼a、b、c都沒法經過release釋放工具
循環引用的場景spa
1、定時器NSTimer代理
2、block的使用調試
3、代理delegate對象
4、父子對象關係(swift)內存
定時器:開發
咱們在使用NSTimer時常常會做爲一個類的屬性使用
而NSTimer在初始化的時候回指定self爲target.這就形成了self—>NSTimer-->self的循環引用的狀況。另外在NSTimer一致處於validata狀態時其引用計數器一直是大於0的
解決辦法:在不使用定時器之後要調用invalidata移除定時器。
block的使用
block在引用外部的變量是,會對外部變量進行copy操做。在(ARC)模式下會對變量進行強引用,(MRC)模式下變量retainCount加1。當一個類把block做爲成員變量時,在block內部使用了這個類自己。形成self—>block-->self或者self-->block-->類的成員變量循環引用的狀況。
解決辦法:在MRC模式下,在給block賦值時在外部用__blockmySelf = self;用__block修飾使用到的類。
在ARC模式下,用__weak修飾
代理:
代理協議也是一個典型的場景,須要你使用弱引用來避免循環引用。將代理聲明爲 weak 是一個即好又安全的作法
父子對象關係
父子對象關係是一個循環引用的典型案例,不幸的是,它也是惟一一個存在於蘋果文檔中的案例。典型的解決方法就是,在子類定義一個指向父類的變量,聲明爲 weak 弱引用,從而避免循環引用。
在 swift 中子類指向父對象的變量是一個弱引用,這就迫使咱們將該弱引用定義爲 optional 類型。若是不使用 optional 能夠有另外一種作法,將指向父對象的變量聲明爲「無主引用(unowned)」(代表咱們不持有該對象,也不對其進行內存管理)。然而在這種狀況下,咱們必須很是當心,確保只要還有子對象指向它,父對象不變成 nil,不然會直接閃退。
調試:
使用 Instruments 調試循環引用
XCode 自帶了一個很強大的工具 Instruments,用於檢測和定位循環引用。一旦你的 app 開發結束,即將提交到 Apple Store,先分析你的 app 是一個好的習慣。Instruments 有不少組件,能夠用來分析 app 的不一樣方面,可是咱們如今關心的是 Leak 選項。