循环引用原因:
初始化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使用中间类,解决循环引用
我们可以添加一个中间类,将TimerProxy
的target
设为弱引用并指向当前控制器就不会产生循环引用了
代码:
- (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
将消息转发给当前视图控制器,解决循环引用。
网友评论