iOS迴圈引用問題

2022-03-30 18:00:47 字數 1733 閱讀 1575

今天面試問道了迴圈引用,所以就看了看,原來只是知道使用了block容易造成迴圈引用。今天就來簡單的介紹一些迴圈引用。

先來簡單介紹一下什麼是迴圈引用?

迴圈引用可以簡單的理解成:a物件引用了b物件,b物件又引用了a物件。兩者相互保持對方的乙個引用。導致任何時候計數都不為0,最終兩者都無法釋放。

產生迴圈引用的方式:

1、nstimer

比如說我在乙個類中宣告了乙個nstimer計時器類。而在nstimer 的方法

+ (nstimer *)scheduledtimerwithtimeinterval:(nstimeinterval)seconds

target:(

id)target

selector:(sel)aselector

userinfo:(

id)userinfo

repeats:(bool)repeats

當我們在aselector中呼叫了自己的屬性或者方法時(比如呼叫了自己的self.class),那麼當我們例項化這個類之後然後我們讓他延遲幾秒釋放,那麼我們會發現time中的aselector會一直執行。現在就來簡單的分析一下吧:

timer沒有呼叫invalidate方法是不會因為類的釋放而停止的。而對於類例項來說:它認為timer沒有執行完畢,所以沒有機會進入dealloc。迴圈引用,相互等待。所以我們可以在類例項釋放之前手動呼叫一下nstimer的invalidate方法。還有就是下面的**:

__weak classa *weakself =self;

timer = [nstimer scheduledtimerwithtimeinterval:1.0f target:weakself selector:@selector(starttimer) userinfo:nil repeats:yes];

所以我們在使用nstimer時一定要注意nstimer的invalidate時機。

在下面更新中,對nstimer進行了重新說明。nstimer是會造成迴圈引用,但是只要我們在合適的地方將其停止並釋放就沒問題。但是你有的時候並不能保證其一定會釋放,比如我點選了倒計時,但是我沒有等倒計時結束就返回,如果是viewcontroller,你可以在檢視將要消失的時候呼叫停止和釋放方法。但是如果不是在viewcontroller中就不確定了。所以在github上的demo上有個zgweaktimertarget,可以巧妙地解決迴圈引用問題。更多請參見這裡.

2、block

例如我們定義了乙個block塊,然後作為了乙個類的屬性變數,那麼當我們在這個塊中呼叫自己的屬性或者方法的時候就會產生迴圈引用。

解決迴圈引用方法:通過__weak宣告乙個self的新變數來代替原來的self。這樣在塊中可以通過這個弱引用self來防止block中對self進行strong引用。

3、delegate

一般情況下我們宣告delegate時使用assign賦值,因為賦值屬性不會增加計數。

如果乙個uitableviewcontroller 物件a通過retain獲取了uitableview物件b的所有權,這個uitableview物件b的delegate又是a, 如果這個delegate是retain方式的,那基本上就沒有機會釋放這兩個物件了。

2023年6月7日更新:

引用迴圈定義:

所謂的「引用迴圈」是指雙向的強引用,所以那些「單項的強引用」(block強引用self)是沒有問題的。 

2023年6月19日更新:

近期分享的ppt和demo。詳見這裡。

iOS之迴圈引用問題

記憶體中和變數有關的分割槽 堆 棧 靜態區。其中,棧和靜態區是作業系統自己管理的,對程式設計師來說相對透明,所以,一般我們只需要關注堆的記憶體分配,而迴圈引用的產生,也和其息息相關,即迴圈引用會導致堆裡的記憶體無法正常 從而導致記憶體洩漏。1 棧區 stack 由編譯器自動分配釋放 存放函式的引數值...

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...