天天看點

NSTimer的循環引用

前天面試問到NSTimer的循環引用,面試者說了一個他從網上找的方法:

NSTimer

建立一個類方法,内部設定

target

NSTimer

類,然後通過

block

回調供外部使用。

當時聽到這個感覺有個問題,目前控制器确實會正常釋放,那怎麼確定定時器也正常釋放了呢?他當時說沒有考慮過這個問題。我想了一下自己使用定時器的時候,觀察的是定時器方法,通過調用

invalidate

方法,保證計時器方法不會再調用,就o了。那這樣真的可以保證定時器釋放嗎?檢視下API說明如下:

Timers work in conjunction with run loops. Run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
           

這裡說

Run loops

會強引用

Timers

,是以就算我們外部沒有強引用

Timers

,也能夠正常使用它的計時功能。

Once scheduled on a run loop, the timer fires at the specified interval until it is invalidated. A nonrepeating timer invalidates itself immediately after it fires. However, for a repeating timer, you must invalidate the timer object yourself by calling its invalidate method. Calling this method requests the removal of the timer from the current run loop; as a result, you should always call the invalidate method from the same thread on which the timer was installed. Invalidating the timer immediately disables it so that it no longer affects the run loop. The run loop then removes the timer (and the strong reference it had to the timer), either just before the invalidate method returns or at some later point. Once invalidated, timer objects cannot be reused.
           

這裡說明了對于一個重複計時的定時器,通過調用

invalidate

方法,定時器會終止并從

Run loops

中移除。也就是說我用完計時器然後調用

invalidate

方法就不會出現記憶體洩露了。

其實上面那個面試者說的方法,網上也有,最終也是通過調用

invalidate

解決的。

通過上面的分析,正确使用

Timer

就不會造成記憶體洩露了,那麼該如何證明呢。一般來說,如果對象釋放,一定會走

dealloc

方法。隻要重寫

dealloc

方法就行了。但是這個類是系統類,我們沒有辦法直接在源檔案中寫,那該怎麼寫呢?

1. 子類化并重寫

dealloc

方法。

Subclassing Notes
    Do not subclass NSTimer.
           

API中說不能夠子類化,是以排除此方案。

2. 通過

category

實作

dealloc

方法。使用此方法,代碼運作的時候會崩潰,應該是一直調用導緻的卡死。

3. 通過

instruments

檢查對象記憶體的開辟量。打開

instruments

并選擇

Allocations

。然後在下部的搜尋框中輸入

timer

,就可以看到計時器對象目前的記憶體暫用量了。

NSTimer的循環引用

繼續閱讀