假设业务需要一个这样含有倒计时功能的商品详情页面,大家肯定会想要使用NSTimer。 如果直接在vc中持有一个NSTimer的话同时会导致vc被runloop强引用,如果没有在合适的时机停止timer(实际上需要释放的时机很难确定,只能在viewDisappear和viewAppear相关的回调中操作timer,逻辑繁琐容易发生错误,我认为最合适的时机是在vc的dealloc流程中释放timer),则会导致vc无法进入dealloc流程,造成内存泄漏。此时的引用分析如下:
简单解释下为什么在DetailVC页面退出后无法进入dealloc流程?因为此时虽然UINavigationController对DetailVC的强引用因为页面对出而释放了,但是runloop依然在强引用DetailVC产生的实例对象,所以无法进入dealloc流程。
按照在vc的dealloc流程中释放timer的思路解决这个问题的话,我的想法是引入一个中间对象,SafeTimer继承自NSObject。作为detailVC的成员变量,通过SafeTmer管理NSTimer,这样DetailVC只被UINavigationController强引用,所以当页面退出后,即被UINavigationController pop后,DetailVC便没有了强引用,所以可以进入dealloc流程,进而释放SafeTimer和其中的NSTimer。这个方案的引用分析如下: