NSTimer循环引用

循环引用原因:

初始化NSTimer的时候,传入的target会被NSTimer强引用,并且控制器强引用NSTimer,所以产生循环引用。

    self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

解决方案

1)合适的时机调用invalidate方法
- (void)viewDidDisappear {
    [super viewDidDisappear];
    [self.timer invalidate];
}
2)target使用中间类,解决循环引用

我们可以添加一个中间类,将TimerProxytarget设为弱引用并指向当前控制器就不会产生循环引用了

代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.timer = [NSTimer timerWithTimeInterval:1.0 target:[TimerProxy timerProxyWithTarget:self] selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

}

@interface TimerProxy : NSObject
@property (nonatomic, weak) id target;
+ (instancetype)timerProxyWithTarget:(id)target;
@end

@implementation TimerProxy
+ (instancetype)timerProxyWithTarget:(id)target
{
    TimerProxy *instance = [TimerProxy new];
    instance.target = target;
    
    return instance;
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.target;
}
@end

这里使用到了runtime消息转发机制,forwardingTargetForSelector将消息转发给当前视图控制器,解决循环引用。

你可能感兴趣的:(NSTimer循环引用)