使用NSTimer的时候可能存储内存泄漏问题,例如:当控制器销毁时,会发现dealloc没有被调用,问题的原因在于timer对控制器对象有强引用,即使是使用了weakSelf
#import "ViewController.h" @interface ViewController () @property (nonatomic, strong) NSTimer *timer; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. __weak typeof(self) weakSelf = self; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:weakSelf selector:@selector(timerInvoke:) userInfo:nil repeats:YES]; self.timer = timer; self.timer = timer; } - (void)timerInvoke:(NSTimer *)timer{ NSLog(@"%s",__func__); } - (void)dealloc{ [self.timer invalidate]; NSLog(@"%s",__func__); } @end
如需解决这个问题,就得解决问题的原因timer对target对象的强引用,方式可以修改timer的引用为间接对象target,通过间接对象传递真实监听对象和方法,那么当真实对象的dealloc销毁时,调用[self.timer invalidate]; 那么对象既可以销毁,timer也可以销毁,timer销毁了,间接对象target也就可以销毁.
#import "ViewController.h" #import "HJTimerTarget.h" @interface ViewController () @property (nonatomic, strong) NSTimer *timer; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // __weak typeof(self) weakSelf = self; // NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:weakSelf selector:@selector(timerInvoke:) userInfo:nil repeats:YES]; // self.timer = timer; NSTimer *timer = [HJTimerTarget scheduledTimerWithTimeInterval:2 target:self selector:@selector(timerInvoke:) userInfo:nil repeats:YES]; self.timer = timer; } - (void)timerInvoke:(NSTimer *)timer{ NSLog(@"%s",__func__); } - (void)dealloc{ [self.timer invalidate]; NSLog(@"%s",__func__); } @end
#import <Foundation/Foundation.h> @interface HWWeakTimerTarget : NSObject @property (nonatomic, weak) id target; @property (nonatomic, assign) SEL selector; @property (nonatomic, weak) NSTimer* timer; + (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats; @end
#import "HWWeakTimerTarget.h" @implementation HWWeakTimerTarget + (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats { HWWeakTimerTarget* timerTarget = [[HWWeakTimerTarget alloc] init]; timerTarget.target = aTarget; timerTarget.selector = aSelector; timerTarget.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:timerTarget selector:@selector(fire:) userInfo:userInfo repeats:repeats]; return timerTarget.timer; } - (void) fire:(NSTimer *)timer { if(self.target) { [self.target performSelector:self.selector withObject:timer.userInfo]; } else { [self.timer invalidate]; } } - (void)dealloc{ NSLog(@"%s",__func__); } @end
运行结果:
-[ViewController timerInvoke:] -[ViewController timerInvoke:] -[ViewController timerInvoke:] -[ViewController timerInvoke:] -[HJTimerTarget dealloc] -[ViewController dealloc]