NSTimer保留对象导致内存泄漏

2016-06-04  本文已影响464人  funnyS

在做限时支付,验证码发送之类的功能时经常需要使用NTimer来做定时器,但是NSTimer在invalidate之前会保留持有它target对象,导致targtet对象无法释放,即使在delloc中:
- (void)dealloc{
[self.timer invalidate];
self.timer = nil;
}
也无法释放,因为target对象一直被引用就不会进入delloc方法。

首先,在分类中添加下面这段代码:

#import <Foundation/Foundation.h>

@interface NSTimer (Addtions)

/**
 *  计时器动作
 *
 *  @param interval 时间
 *  @param block    事件
 *  @param repeats  是否重复
 */
+ (NSTimer *)sf_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                         block:(void(^)())block
                                       repeats:(BOOL)repeats;


@end
#import "NSTimer+Addtions.h"

@implementation NSTimer(Addtions)

/**
 *  计时器动作
 *
 *  @param interval 时间
 *  @param block    事件
 *  @param repeats  是否重复
 */
+ (NSTimer *)sf_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
                                    block:(void(^)())block
                                  repeats:(BOOL)repeats{
    return [self scheduledTimerWithTimeInterval:interval
                                         target:self
                                       selector:@selector(private_blockinvoke:)
                                       userInfo:[block copy]
                                        repeats:repeats];
}


+ (void)private_blockinvoke:(NSTimer *)timer{
    void (^block)() = timer.userInfo;
    if (block) {
        block();
    }
}

@end

现在我们直接使用这个函数去创建计时器:

    self.timer = [NSTimer sf_scheduledTimerWithTimeInterval:1.0
                                                      block:^{
                                                          [self timerAction];
                                                      } repeats:YES];

这时依然会形成“保留环”,因为block保留了self对象,self又持有timer属性。所以在调用函数之前要使用weak引用来打破它:

    __weak RegistVC *weakSelf = self;
    self.timer = [NSTimer sf_scheduledTimerWithTimeInterval:1.0
                                                      block:^{
                                                          RegistVC *strongSelf = weakSelf;
                                                          [strongSelf timerAction];
                                                      } repeats:YES];

到这里,问题就算解决了,当self的最后一个引用将其释放的时候,self就会被释放了,如果忘记在delloc中调用计时器的invalidate方法,则weakSelf会变为nil。在调试过程中也能看到对象delloc了,而不是再持有一段时间甚至永远不会释放。

上一篇下一篇

猜你喜欢

热点阅读