直接官方介绍看图
image将target
强引用,引用计数+1,因此避免循环饮用的理论:
@property (weak ,nonatomic) NSTimer *timer;
这样写不通的。因为target
引用计数已经+1,target
如果是ViewController
,页面栈,pop
出时,引用计数不会变成0,因此不会调用dealloc
,ViewController
依然在。
调用NSTimer
方法中的invalidate
,可以将target
引用计数-1,由此可以解决内存泄漏问题。
NSTime中Block官方介绍:
image官方介绍:Block的方式可以避免循环引用
Block的方式,NSTimer
不会将target
引用计数+1,因此,只关注Block循环引用问题即可。target
会调用dealloc
。
需要在dealloc
中调用NSTimer
的invalidate
方法,
如果不调用NSTimer
的invalidate
方法,NSTimer
会一直执行,而target
是nil
。具体原因和Runloop
有关系,后续我们单独再讲Runloop
和NSTimer的关系
调试代码如下
@property (strong ,nonatomic) NSTimer *timer;
- (void)dealloc {
NSLog(@"Timer invalidate 前 = %ld",CFGetRetainCount((__bridge CFTypeRef)(self.timer)));
[self.timer invalidate];
NSLog(@"Timer invalidate 后 = %ld",CFGetRetainCount((__bridge CFTypeRef)(self.timer)));
NSLog(@"TestVC释放了%@",self);
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
// [self.timer invalidate];
// NSLog(@"retainCount3 = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
// self.timer = nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// NSLog(@"retainCount0 = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
[self creatTimer];
}
- (void)creatTimer {
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
// [self.timer fire];
}
- (NSTimer*)timer{
if(_timer==nil) {
__weak typeof(self) weakSelf = self;
// NSLog(@"retainCount1 = %ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
// _timer = [NSTimer timerWithTimeInterval:1 target:weakSelf selector:@selector(timerForOverTimeOrder:) userInfo:weakSelf repeats:YES];
// NSLog(@"定时器前%@",weakSelf);
_timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
// NSLog(@"fafafdfadfadxf%@",weakSelf);
NSLog(@"retainCount4 = %ld",CFGetRetainCount((__bridge CFTypeRef)(timer)));
// NSLog(@"fafafdfadfadxf%@",timer.userInfo);
// NSLog(@"dfafdada%@",self);
}];
NSLog(@"retainCount2 = %ld",CFGetRetainCount((__bridge CFTypeRef)(self.timer)));
}
return _timer;
}
- (void)timerForOverTimeOrder:(id)info {
NSLog(@"%@",info);
// NSLog(@"1111");
}
网友评论