美文网首页
iOS定时器 NSTimer、CADisplayLink循环引用

iOS定时器 NSTimer、CADisplayLink循环引用

作者: yyggzc521 | 来源:发表于2018-11-19 19:55 被阅读0次

    如果CADisplayLink、NSTimer对target强引用,同时target又对CADisplayLink、NSTimer强引用,那么此时就会引发循环引用!

    @property(nonatomic,strong) CADisplayLink *displayLink;//self强引用了CADisplayLink
    
    // CADisplayLink内部又强引用了self
    self. displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(linkTest)];
    [self. displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
    - (void)linkTest {
    
        NSLog(@"%s",__func__);
    }
    
    - (void)dealloc {//循环引用导致dealloc方法不会被调用
    
        NSLog(@"%s", __func__);
        [self. displayLink invalidate];
    }
    

    同理下面NSTimer也是这种情况

    @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 {
       NSLog(@"%s", __func__);
       [self.timer invalidate];
    }
    

    解决方案

    1、使用NSTimer的类方法,并弱引用self
    __weak typeof(self) weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
    
          [weakSelf timerTest];
    }];
    
    2、通过中间代理对象的方式
    1728484-4406c7791f5339c3.png
    @interface ZCMiddleProxy : NSObject
    
    //此处用weak修饰
    @property (nonatomic, weak) id target;
    
    + (instancetype)proxyWithTarget:(id)target;
    
    @end
    
    
    #import "ZCMiddleProxy.h"
    
    @implementation ZCMiddleProxy
    
    + (instancetype)proxyWithTarget:(id)target {
    
       ZCMiddleProxy *proxy = [[ZCMiddleProxy alloc] init];
       proxy.target = target;
       return proxy;
    }
    
    // 消息转发机制(会先发送消息、再动态解析、最后再消息转发)
    - (id)forwardingTargetForSelector:(SEL)aSelector {
    
        return self.target;
    }
    @end
    
    //timer改为这么使用,就可以解决循环引用问题
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[ZCMiddleProxy proxyWithTarget:self] selector:@selector(timerTest) userInfo:nil repeats:YES];
    
    

    参考链接:https://www.jianshu.com/p/524bc26855d3

    相关文章

      网友评论

          本文标题:iOS定时器 NSTimer、CADisplayLink循环引用

          本文链接:https://www.haomeiwen.com/subject/lbvafqtx.html