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
  • 相关阅读:
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    125. Valid Palindrome
    124. Binary Tree Maximum Path Sum
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    120. Triangle
    119. Pascal's Triangle II
  • 原文地址:https://www.cnblogs.com/xwoder/p/4780121.html
Copyright © 2011-2022 走看看