对于以下代码:
@property (strong, nonatomic) NSTimer *timer; self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTest) userInfo:nil repeats:YES]; - (void)timerTest { NSLog(@"%s", __func__); } - (void)dealloc { [self.timer invalidate]; }
运行代码之后,发现当前对象并没有销毁,定时器并没有销毁,其实是由于当前对象对timer进行强引用,而timer中的target又对当前对象进行强应用,导致循环引用
解决这种循环引用的有两种,一个timer创建的时候用block代码如下,并声明weakSelf属性,代码如下:
__weak typeof(self) weakSelf = self; self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) { [weakSelf timerTest]; }];
第二种创建一个中间对象,里面声明一个weak的target的对象,再利用runtime的转发机制,有target去执行
创建LBTemp的类,代码如下:
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface LBTemp : NSObject + (instancetype)tempWithTarget:(id)target; @property (weak, nonatomic) id target; @end #import "LBTemp.h" @implementation LBTemp + (instancetype)tempWithTarget:(id)target { LBTemp *temp = [[LBTemp alloc] init]; temp.target = target; return temp; } - (id)forwardingTargetForSelector:(SEL)aSelector { return self.target; } @end
创建timer代码如下:
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[LBTemp tempWithTarget:self] selector:@selector(timerTest) userInfo:nil repeats:YES];
同样的CADisplayLink循环引用问题也可以用第二种方法解决