定时器内存管理 3 种方案 DEMO
CADisplayLink、NSTimer使用注意
CADisplayLink、NSTimer会对target产生强引用,target又对它们产生强引用,那么就会引发循环引用
先看一段示例代码
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
// self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(start)];
// [self.link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:weakSelf selector:@selector(start) userInfo:nil repeats:YES];
}
//开始
-(void)start {
NSLog(@"%s",__func__);
}
-(void)dealloc {
[self.timer invalidate];
}
timer 和 self 进行了相互引用.导致不能释放. 那么 传入一个 weak 修饰的 self 进去可以解决吗? 答案是不能的!
猜测 timer 内部有一个strong 属性 对传进来的 target 进行强引用.所以导致不能释放
解决方案: 之所以会导致内存不释放, 是因为循环引用导致的. 我们无法改变 NSTimer 里面的属性. 那么我们加入一个"第三者",来打破循环引用
image.png
主要代码:
#import "TimerPersent.h"
@implementation TimerPersent
+(instancetype)initWithObject:(NSObject *)obj {
TimerPersent *persent = [[TimerPersent alloc] init];
persent.target = obj;
return persent;
}
//消息转发. 让传进来的 target去响应
- (id)forwardingTargetForSelector:(SEL)aSelector {
return self.target;
}
@end
NSTimer 的创建
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:[TimerPersent initWithObject:self] selector:@selector(start) userInfo:nil repeats:YES];
完美解决.
定时器采用使用 block,传入 weakSelf 可以解决循环引用
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
// self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(start)];
// [self.link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
__weak typeof(self) weakSelf = self;
// self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:weakSelf selector:@selector(start) userInfo:nil repeats:YES];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:true block:^(NSTimer * _Nonnull timer) {
[weakSelf start];
}];
}
//开始
-(void)start {
NSLog(@"%s",__func__);
}
-(void)dealloc {
[self.timer invalidate];
NSLog(@"销毁了");
}
网友评论