在一次实践中,创建了控制器,控制器中创建了timer和手势,控制器的view被addsubview到window上,手动或者3s后从window上移除。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor=RGBA_COLOR(0, 0, 0, 0.4);
_timer=[NSTimer timerWithTimeInterval:3.0
target:self
selector:@selector(action)
userInfo:nil
repeats:NO];
UITapGestureRecognizer* tap= [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(action)];
[self.view addGestureRecognizer:tap];
}
并将timer加入到了当前的runloop中
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self startTimer];//开始计时
}
- (void)startTimer {
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
-(void)action
{
[_timer invalidate];
_timer = nil;
if (![self popNext]) {
[self.view removeFromSuperview];
}else {
_timer=[NSTimer timerWithTimeInterval:3.0
target:self
selector:@selector(action)
userInfo:nil
repeats:NO];
[self startTimer];
}
}
运行在iOS9以下的系统手势触发会发上crash。
屏幕快照 2016-12-19 22.03.48.png原因是该控制器创建后只有timer持有了该控制器。( timer对target对象强引用,当timer中repeat设置为NO时,timer到时间触发执行action后即对target不再引用;当timer中repeat设置为YES时,timer会持续持有target,直到手动invalidate timer后会释放。)当timer被invalidate后对象就释放了,再次访问timer就会报错。
可是ios9及以上的系统就不会,由于ios9以上系统对内存回收机制做了修改,当对象函数运行中对对象本身进行释放时,会到函数运行结束完后才真正释放,ios9以前的系统会在函数运行中立即释放对象,不会等到函数运行结束,如果该函数之后对对象进行操作就会crash。
网友评论