1.为什么会引起循环引用?
由于NSTimer会引用控制器self,而self又持有NSTimer对象,所以形成循环引用,在dealloc中停止定时器是不会被执行的,Timer也永远不会被释放,这样也造成了内存泄漏。
2.如何解决?
1.先说第一个比较麻烦的解决方法:
在viewwillappear方法中开启定时器,再在viewwilldisappear里面去关闭定时器。
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (!self.timer) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(showMsg) userInfo:nil repeats:YES];
}
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
}
这样虽然可以解决循环引用的问题,但是维护起来比较麻烦。
2.封装一个NStimer的category,提供block形式的接口:
#import <Foundation/Foundation.h>
@interface NSTimer (TimerBlock)
/**
分类解决NSTimer在使用时造成的循环引用的问题
@param interval 间隔时间
@param block 回调
@param repeats 用于设置定时器是否重复触发
@return 返回NSTimer实体
*/
+ (NSTimer *)block_TimerWithTimeInterval:(NSTimeInterval)interval block:(void(^)())block repeats:(BOOL)repeats;
@end
#import "NSTimer+TimerBlock.h"
@implementation NSTimer (TimerBlock)
+ (NSTimer *)block_TimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)())block repeats:(BOOL)reqeats{
return [self timerWithTimeInterval:interval target:self selector:@selector(blockSelector:) userInfo:[block copy] repeats:reqeats];
}
+ (void) blockSelector:(NSTimer *)timer{
void (^block)() = timer.userInfo;
if (block) {
block();
}
}
@end
这个方式调用者是NStimer自己,这样我们在使用timer时,由于target的改变,就不再有循环引用的问题了。