NSTimer 的内存泄露问题

正常来讲,我们开启一个Timer有几种办法,
1. 直接使用
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
这个不用关心runloop的事情,也不用关心mode,默认添加到当前runloop的默认mode
2. 首先创建Timer 然后添加到runloop里面。
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti
target:(id)target
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats

这里的添加的runloop里面还要选择mode,所以注意可能会阻塞runloop里面的相同mode下的其他进程(比如滚动tableview,timer暂停)。这是个坑。需要注意。


内存泄露

内存泄露的原因是Timer不停止,则会一直保有一份target(比如self),

. This means that as long as a timer remains valid, its target will not be deallocated

这样self如果是controller,controller 被 pop 的时候就会发生内存泄露,因而不会被销毁。解决方法首先是在
- (void)viewWillDisAppear
停止timer,并且置为nil,不过这样再pop回来timer就没了,就要重新启动timer,如果也有倒计时的话,计数就不对了。比较经济实惠的方法是用block解决。大概想法就是让Nstimer 类做为target,解决内存无法释放的问题。
@interface NSTimer (XXBlocksSupport)
+ (NSTimer *)xx_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats;
@end
@implementation NSTimer (XXBlocksSupport)
+ (NSTimer *)xx_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(xx_blockInvoke:)
userInfo:[block copy]
repeats:repeats];
}
+ (void)xx_blockInvoke:(NSTimer *)timer {
void (^block)() = timer.userinfo;
if(block) {
block();
}
}
@end

注意:以上NSTimer的target是NSTimer类对象,类对象本身是个单利,此处虽然也是循环引用,但是由于类对象不需要回收,所以没有问题。但是这种方式要注意block的间接循环引用,当然了,解决block的间接循环引用很简单,定义一个weak变量,在block中使用weak变量即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值