zoukankan      html  css  js  c++  java
  • NSTimer与循环引用

    代码:

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (strong, nonatomic) NSTimer *timer;
    
    - (void)doSomething:(NSTimer *)timer;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 编程提示
        // A timer maintains a strong reference to its target.
        // This means that as long as a timer remains valid, its target will not be deallocated.
        // As a corollary, this means that it does not make sense for a timer’s target to try to invalidate the timer in its dealloc method,
        // the dealloc method will not be invoked as long as the timer is valid.
        
        // target参数
        // The object to which to send the message specified by aSelector when the timer fires.
        // The timer maintains a strong reference to this object until it (the timer) is invalidated.
        NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(doSomething:) userInfo:nil repeats:YES];
        
        // The receiver retains aTimer.
        // To remove a timer from all run loop modes on which it is installed, send an invalidate message to the timer.
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        
        self.timer = timer;
    }
    
    - (void)doSomething:(NSTimer *)timer {
        NSLog(@"%s", __func__);
    }
    
    - (void)dealloc {
        NSLog(@"%s", __func__);
        [self.timer invalidate];
    }
    
    @end

    上述代码中,由于timer会在其有效期内保持对其target的强引用,而target自身也就是当前的viewController又通过一个使用strong修饰符修饰的属性对timer产生强引用,最终产生循环引用。

    并且在本例中,由于runLoop会引用被添加至其中的timer,从而产生了一个永远无法被自行打破的循环引用。

    由于循环引用的存在,即便当前viewController从导航控制器的导航栈中弹出,其dealloc方法也不会被调用。所以在dealloc方法中,调用timer的invalidate方法是没有意义的。

    一种可行的办法是重写viewController的viewWillDisappear:或viewDidDisappear:方法,在其方法体内调用timer的invalidate方法,从而解除timer对target即viewController的强引用,最终打破循环引用。

    代码-修改版:

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (strong, nonatomic) NSTimer *timer;
    
    - (void)doSomething:(NSTimer *)timer;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(doSomething:) userInfo:nil repeats:YES];
    
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        
        self.timer = timer;
    }
    
    - (void)doSomething:(NSTimer *)timer {
        NSLog(@"%s", __func__);
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        NSLog(@"%s", __func__);
        [self.timer invalidate];
    }
    
    - (void)dealloc {
        NSLog(@"%s", __func__);
    }
    
    @end
  • 相关阅读:
    NEC 框架规范 css reset
    NEC 工程师规范
    NEC html规范
    【bzoj2839】【集合计数】容斥原理+线性求阶乘逆元小技巧
    【bzoj1562】【[NOI2009]变换序列】匈牙利算法的性质利用
    【bzoj4808】【马】二分图最大点独立集+简单感性证明
    【hdu1150】【Machine Schedule】二分图最小点覆盖+简单感性证明
    【bzoj4950】【 [Wf2017]Mission Improbable】贪心+二分图匹配
    【bzoj4443】【[Scoi2015]小凸玩矩阵】二分+二分图最大匹配
    【bzoj1977】【严格次小生成树】倍增维护链上最大次大值
  • 原文地址:https://www.cnblogs.com/xwoder/p/4780121.html
Copyright © 2011-2022 走看看