您的位置:首页 > 其它

NSTimer 的内存泄露问题

2016-06-12 21:55 218 查看
正常来讲,我们开启一个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变量即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  NSTimer 内存泄露