NSTimer的循环引用

前天面试问到NSTimer的循环引用,面试者说了一个他从网上找的方法:

NSTimer新建一个类方法,内部设置targetNSTimer类,然后通过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,就可以看到计时器对象当前的内存暂用量了。

如图

猜你喜欢

转载自blog.csdn.net/jianghui12138/article/details/81168062