iOS開發 迴圈引用

2021-09-11 02:32:23 字數 2344 閱讀 4843

-- :表示弱引用。

-> :表示強引用。

迴圈引用可以簡單理解為物件a引用了物件b,而物件b又引用了物件a:a -> b -> a,此時雙方都同時保持對方的乙個引用,導致任何時候雙方的引用計數都不為0,雙方始終無法釋放就造成記憶體洩漏。

當然不只是兩個物件之間相互引用會形成迴圈引用,多個物件之間相互引用最終形成環同樣會形成迴圈引用。

例如:a -> b -> c -> a。

1、delegate

self.tableview.delegate = self;
如果 delegate使用strong修飾就會構成迴圈引用:self -> tableview -> delegate -> self。

所以在定義delegate屬性時使用weak便能解決這一問題:self -> tableview -- delegate -> self。tableview和delegate之間不是強引用,所以構不成迴圈。

規避delegate迴圈引用的殺手鐗也是簡單到哭:定義delegate屬性時請用assign(mrc)或者weak(arc),千萬別手賤玩一下retain或者strong。

2、nstimer

詳情看我的這篇部落格:ios開發-nstimer**

3、block

並不是所有block都會產生迴圈引用,block是否產生迴圈引用是需要我們去判斷的,例如:

[uiview animatewithduration:0.0 animations:^];
這樣是不會產生迴圈引用,因為這個block不被self持有,是被uiview的類物件持有,這個block和self沒有任何關係,所以可以任意使用self。

而像下面這樣,self -> reachabilitymanager -> block -> self,才會產生迴圈引用,並且xcode給出了迴圈引用warning。

網上大部分部落格都表述為"block裡使用了self導致迴圈引用",但事實真的是如此嗎?其實這種說法是不嚴謹的,不一定要顯式地出現"self"字眼才會引起迴圈引用。不通過self去訪問變數,而是直接訪問例項變數,如下: 

即使在block內部沒有顯式地出現"self",只要你在block裡用到了self所擁有的東西,一樣會出現迴圈引用!

解決block迴圈引用的方法是使用__weak修飾self,然後在block裡使用被修飾後的weakself來代替self

__weak __typeof(self) weakself = self;

[self.reachabilitymanager setreachabilitystatuschangeblock:^(afnetworkreachabilitystatus status) ];

但是僅僅使用__weak修飾self存在乙個缺陷:__weak可能會導致記憶體提前**weakself,在未執行nslog()時,weakself就已經被釋放了,然後執行nslog()時就列印(null)。所以為了解決這個缺陷,我們需要這樣在block內部再用__strong去修飾weakself:

__weak __typeof(self) weakself = self;

[self.reachabilitymanager setreachabilitystatuschangeblock:^(afnetworkreachabilitystatus status) ];

我們發現上述這個方法確實解決所有問題,但是可能會有兩個不理解的點:

使用最終方法基本可以解決百分之九十九的block的迴圈引用問題,但還是希望不要盲目遇到block中有self就直接下面這兩行**上去,最好能夠理解地運用,根據實際情況去運用。

__weak __typeof(self) weakself = self

__strong __typeof(weakself) strongself = weakself

我們最後把轉換強、弱引用的**封裝為巨集定義,方便使用與閱讀。 

//弱引用

#define weakself(weakself) __weak __typeof(self) weakself = self

//強引用

#define strongself(strongself) __strong __typeof(weakself) strongself = weakself

當然這樣使用了巨集後,還是有一些缺陷:

iOS迴圈引用

class viewcontroller uiviewcontroller 迴圈引用的方法 func cycliclead completionback escaping void 當物件銷毀時會呼叫 deinit oc方式 weak typeof self weakself self self.b...

iOS開發中的迴圈引用問題

nstimer經常會被作為類的成員變數,而nstimer初始化時要指定self為target,造成迴圈引用。另一方面,若timer一直處於validate的狀態,則其引用計數將始終大於0。先看一段nstimer使用的例子 arc模式 解決方案 自定義類 wsweaktimertarget h檔案 i...

iOS 看穿迴圈引用

我們在寫程式的時候 閉包能夠使 更加的簡潔 相信大家都用過mjrefresh吧 下拉重新整理 666 configuretableview tableview configuretableview alloc initwithframe cgrectzero style uitableviewsty...