NSTimer经常会引起循环引用,以下是几种解决方案:
一:使用block的NSTimer,如下:
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelftimerTest];
}];
二:使用代理对象(NSProxy),自定义一个子类WPProxy继承于NSProxy。代码如下:
创建timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[WPProxy proxyWithTarget:self] selector:@selector(xxx) userInfo:nil repeats:YES];
在创建的子类.m文件中实现以下方法:
+ (instancetype)proxyWithTarget:(id)target
{
// NSProxy对象不需要调用init,因为它本来就没有init方法
WPProxy*proxy = [WPProxy alloc];
proxy.target= target; // target在点.h文件中定义,weak修饰属性
returnproxy;
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)sel
{
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation*)invocation
{
[invocationinvokeWithTarget:self.target];
}
三 NSTimer依赖于RunLoop,如果RunLoop的任务过于繁重,可能会导致NSTimer不准时,GCD的定时器会更加准时。代码实现如下:
{
dispatch_queue_t queue = dispatch_queue_create("timer", DISPATCH_QUEUE_SERIAL);
// 创建定时器
dispatch_source_ttimer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, queue);
dispatch_source_set_timer(timer,
dispatch_time(DISPATCH_TIME_NOW,2 *NSEC_PER_SEC),
1.0 *NSEC_PER_SEC,0);
// 设置回调
dispatch_source_set_event_handler(timer, ^{
NSLog(@"1111");
});
// 启动定时器
dispatch_resume(timer);
}