zoukankan      html  css  js  c++  java
  • 初识iOS NSTimer 循环引用不释放问题

     原文转自 :http://www.codecate.com/code/?p=77

    最近开发遇到NSTimer Target 造成循环引用问题,不释放,以下是解决方案。

    stackoverflow上的一个解决方案

    http://stackoverflow.com/questions/16821736/weak-reference-to-nstimer-target-to-prevent-retain-cycle

    原文如下

    Weak Reference to NSTimer Target To Prevent Retain Cycle

    I’m using an NSTimer like this:

    timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(tick) userInfo:nil repeats:YES];

    Of course, NSTimer retains the target which creates a retain cycle. Furthermore, self isn’t a UIViewController so I don’t have anything like viewDidUnload where I can invalidate the timer to break the cycle. So I’m wondering if I could use a weak reference instead:

    __weak id weakSelf = self;
     timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];
     I've heard that the timer must be invalidated (i guess to release it from the run loop). But we could do that in our dealloc, right?
    
    - (void) dealloc {
     [timer invalidate];
    }

    Is this a viable option? I’ve seen a lot of ways that people deal with this issue, but I haven’t seen this.

    解决方案

    The proposed code:

    __weak id weakSelf = self;
     timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];

    has the effect that (i) a weak reference is made to self; (ii) that weak reference is read in order to provide a pointer to NSTimer. It won’t have the effect of creating an NSTimer with a weak reference. The only difference between that code and using a __strong reference is that if self is deallocated in between the two lines given then you’ll pass nil to the timer.

    The best thing you can do is create a proxy object. Something like:

    [...]
     @implementation BTWeakTimerTarget
     {
     __weak target;
     SEL selector;
     }
    [...]
    - (void)timerDidFire:(NSTimer *)timer
     {
     if(target)
     {
     [target performSelector:selector withObject:timer];
     }
     else
     {
     [timer invalidate];
     }
     }
     @end
     Then you'd do something like:
    BTWeakTimerTarget *target = [[BTWeakTimerTarget alloc] initWithTarget:self selector:@selector(tick)];
     timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:target selector:@selector(timerDidFire:) ...];

    Or even add a class method to BTWeakTimerTarget of the form +scheduledTimerWithTimeInterval:target:selector:… to create a neater form of that code. You’ll probably want to expose the real NSTimer so that you can invalidate it, otherwise the rules established will be:

    the real target isn’t retained by the timer;
    the timer will fire once after the real target has begun (and probably completed) deallocation, but that firing will be ignored and the timer invalidated then.

    使用GCD 方式解决代码

    – (void) doSomethingRepeatedly
    {
    // Do it once
    NSLog(@”doing something …”);

    // Repeat it in 2.0 seconds
    __weak typeof(self) weakSelf = self;
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [weakSelf doSomethingRepeatedly];
    });
    }

  • 相关阅读:
    基于springBoot使用templates技术
    springBoot将配置文件读取进对象
    Django学习笔记二十二——Django的简易项目之账户注册的实现
    Django学习笔记二十一——Django的auth模块
    Django学习笔记二十——Django请求流程梳理总结
    Django学习笔记一十八——Django中间件的使用
    Django学习笔记一十五——cookies和session
    Django学习笔记一十九——补充内容:视图中的CBV和FBV (2020-05-15 15:05)
    Django学习笔记一十八——Django的数据库可视化操作
    Django学习笔记一十七——Django的FORM表单
  • 原文地址:https://www.cnblogs.com/OneBlackLee/p/4183767.html
Copyright © 2011-2022 走看看