我们都知道Timer只有在invalidate之后才会从runloop中被移除,repeat为NO的timer在执行一次之后就会自动移除;我们在使用重复的timer的时候,如果是想在dealloc中调用timer的invalidate方法,往往会造成泄漏,target的dealloc方法不会调用,放在界面viewWillAppear创建和viewWillDisappear的时候invalidate,很多场景也不适用(eg: targetVC 跳转到另外界面再回来).
但是 timer 循环引用的本质问题是 :
问题的根本:
- timer强持有target
- runloop强持有timer
- repeat的timer只有在调用了invalidate之后才会被runloop释放
- 为了timer和target的生命周期一致,我们在target的dealloc中invalidate timertarget被强持有了,不会走dealloc,就内存泄漏了
所以 使用weak 并不能解决循环引用问题
可以使用如下解决方案:
我们需要一个中间者能够将timer的selector转发给target,同时让timer去持有这个中间者,那么问题就解决了 这个中间者 可以使用NSProxy 这个类
我们子类化NSProxy,内部weak引用target,在消息转发的时候调用target去执行;这样timer持有的是proxy,target能正常释放,target释放了,timer就释放了、proxy也会释放,内存泄漏问题解决;
网友评论