首页 热点专区 小学知识 中学知识 出国留学 考研考公
您的当前位置:首页正文

Timer 强引用无法释放问题

2024-12-05 来源:要发发知识网

问题描述:

当你使用Timer时,特别repeat时,你的Timer所在类往往无法调用dealloc,也就该类一直有strong reference指向它(使它无法被释放,造成内存泄露)。


问题原理探究:

当你schedule你的timer到runloop时,runloop会对timer持有强引用。而Timer会对它的target或都invocation持有强引用。
runloop --->(strong) timer ---->(strong) target or invocation
在你的timer invalidate之前你的target会一直无法被释放,不管你的target 对timer是持有强引用还是弱引用。强引用的话就是strong reference circle。


解决方案

  1. 你能确保一定会把你的timer invalidate掉。
  2. 如果你无法确保一定会invalidate你的tiemr。就需要引入第三个类,来打破强引用:
 @interface MyClassTimerDeliver : NSObject

@property (nonatomic, weak) id delegate;
- (void)renderExpiredCountdown:(id)sender;

@end

@implementation MyClassTimerDeliver

- (void)renderExpiredCountdown:(id)sender {
    if([self.delegaterespondsToSelector:@selector(renderExpiredCountdown:)]) {
        [self.delegateperformSelector:@selector(renderExpiredCountdown:) withObject:nil];
    }
}
@end

@interface MyClass : SomeSuperClass {
    NSTimer *_timer;
}

@property (nonatomic, strong) MyClassTimerDeliver *timerDeliver;

@end

@implementation MyClass

- (void)dealloc {
    if (_timer) {
        [_timerinvalidate];
        _timer = nil;
        
    }
}

- (void)doTimer {
    // code here actually do the tiemr
}

- (void)renderExpiredCountdown:(id)sender {
    [_timeDeliver.delegatedoTimer];
}

- (void)createTimer {
    _timeDeliver = [[MDMyLotteryDataSourceTimerDeliveralloc] init];
    _timeDeliver.delegate = self;
    //只创建一个定时器NSTimer
    if (!_timer) {
        _timer = [NSTimerscheduledTimerWithTimeInterval:1.0target:_timeDeliverselector:@selector(renderExpiredCountdown:) userInfo:nilrepeats:YES];
        [[NSRunLoopcurrentRunLoop] addTimer:_timerforMode:NSRunLoopCommonModes];//解决滚动的时候计时器就会停止
    }
}

@end
显示全文