NSTimer释放的几种方法
- 我们在开发过程中,总要用到定时器的功能,想必大家一般都是使用NSTimer吧(当然也不排除使用dispatch_source_t或者CADisplayLink,这两种都要比NSTimer更精确)!
当我们在使用NSTimer时,如果销毁timer不及时就会造成循环引用导致内存泄露的问题,所以使用的时候大家都要注意使用得当!
NSTimer销毁时我们调用invalidate方法并把timer对象置为nil;这些代码我们要写在合适的位置,dealloc析构函数才会被调用从而销毁对象.
今天就讲讲如何正确的销毁一个NSTimer吧!
1.- (void)didMoveToParentViewController:(UIViewController *)parent;
此方法会在子视图被添加到父视图控制器或从父视图控制器移除时调用,如果是移除,参数parent为nil
- (void)didMoveToParentViewController:(UIViewController *)parent {
if (!parent) {
[self.timer invalidate];
self.timer = nil;
}
}
2.使用中间者
_target = [NSObject new];//id类型的属性,自己定义的中间者
Method m = class_getInstanceMethod([self class], @selector(fire));
class_addMethod([_target class], @selector(fire), method_getImplementation(m), "v@:");//运行时添加处理的方法
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:_target selector:@selector(fire) userInfo:nil repeats:YES];//创建timer
此时我们在析构函数dealloc中调用:
[self.timer invalidate];
self.timer = nil;
即可释放timer.
3.通过NSProxy作为中间者
首先创建继承自NSProxy的类WMProxy.
WMProxy.h中声明属性
@property (nonatomic ,weak) id target;
WMProxy.m中使用消息转发机制实现两个方法:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
然后我们在需要使用NSTimer的地方引用WMProxy.h
_wmproxy = [WMProxy alloc];//WMProxy的属性
_wmproxy.target = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:_wmproxy selector:@selector(fire) userInfo:nil repeats:YES];//创建timer
此时我们在析构函数dealloc中调用:
[self.timer invalidate];
self.timer = nil;
即可释放timer.
4.使用scheduledTimerWithTimeInterval: repeats: block:方法
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer wm_scheduledTimerWithTimeInterval:1 block:^{
[weakSelf fire];
} repeate:YES];
//此方法是在iOS10.0给出的.当我们需要向下兼容版本时,我们可以通过新建分类,自己处理逻辑来实现方法调用
.h声明类方法
@interface NSTimer (WMTimer)
+ (NSTimer *)wm_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void(^)(void))block repeate:(BOOL)repeats;
@end
.m实现方法及调用
#import "NSTimer+WMTimer.h"
@implementation NSTimer (WMTimer)
+ (NSTimer *)wm_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)(void))block repeate:(BOOL)repeats {
return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(wm_blockHandle:) userInfo:block repeats:repeats];
}
+ (void)wm_blockHandle:(NSTimer *)timer {
void(^block)(void) = timer.userInfo;
if (block) {
block();
}
}
@end
这样.NSTimer就可销毁了!