变更记录

序号 录入时间 录入人 备注
1 2016-08-24 Alfred Jiang -

方案名称

NSTimer - 解决 NSTimer 的循环引用问题导致的内存泄漏

关键字

NSTimer \ 循环引用 \ Retain Cycle \ 内存泄漏

需求场景

  1. 使用 NSTimer 造成对象无法释放,出现循环引用

参考链接

  1. Why’s Blog - iOS 中的 NSTimer(推荐)

详细内容

由于 NSTimertargetself 对象的强引用,造成在 dealloc 方法中无法调用 invalidate
不调用 invalidate 永远不会进入 dealloc 方法,而不进入 dealloc 方法则永远不会调用 invalidate
为了解决这一问题,可以使用如下 category 中提供的方法初始化,避免了 NSTimertargetself 对象的强引用,
这样就可以在 dealloc 方法中正常调用 invalidate

NSTimer+Weak.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#import <Foundation/Foundation.h>

@interface NSTimer (Weak)

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats;

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats;

@end

NSTimer+Weak.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import "NSTimer+Weak.h"

@implementation NSTimer (Weak)

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats
{
return [self scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(timerUpdateWithBlock:)
userInfo:[block copy]
repeats:repeats];
}

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval
block:(void(^)())block
repeats:(BOOL)repeats
{
return [self timerWithTimeInterval:interval
target:self
selector:@selector(timerUpdateWithBlock:)
userInfo:[block copy]
repeats:repeats];
}

+ (void)timerUpdateWithBlock:(NSTimer*)timer{

void (^timerBlock)() = timer.userInfo;
if(timerBlock){

timerBlock();
}
}

@end

效果图

(无)

备注

(无)