基础

iOS之常见循环引用

2020-08-24  本文已影响0人  yayun_he

我们怎么检查循环引用呢,比较简单的是当我们pop或则dismiss时看我们dealloc方法有没有执行即可,也可以自行用Xcode自带工具去分析,自行研究


测试Demo,可自行下载

几种常见循环引用

一: NSTimer,另附不常见控制器循环引用
先说个特殊例子,我们ViewControllerStrong

@property (nonatomic, strong) TimerCycleRef *timerVC;
 _timerVC  = [[TimerCycleRef alloc] initWithNibName:NSStringFromClass([TimerCycleRef class]) bundle:nil];

    [self presentViewController:_timerVC animated:YES completion:^{
    }];

此时会发现我们TimerCyceVC的dealloc不会执行,好了下面说NSTimer

首先我们present一个TimerCycleRef


截屏2020-08-23 下午9.48.43.png

然后创建Timer,并重写了dealloc方法,当我们dismiss时不会执行dealloc,这是就循环引用了,demo中解释

解决方案在注释中,写了两种比较简单的方案,还有其他,可自行查资料学习

截屏2020-08-23 下午10.31.12.png

看打印log

截屏2020-08-23 下午10.30.23.png

二:block循环引用

介绍正常使用逆向传值时,是不会造成循环引用的
bVC定义一个blcok

typedef void(^MyBlcok)(NSString *str);
@interface bVC : UIViewController
@property (nonatomic, copy) MyBlcok blcok;

点击返回时,执行blcok

//    不会循环引用
 //   self.blcok(@"bVC --- >Hello");
//    self.blcok(self.str);
    self.blcok(self.label.text);
    [self dismissViewControllerAnimated:YES completion:nil];
  /*------------------正常用时不会循环引用的---------------------*/
    // blcok界面传值用法
    // 本身就没有对bvc强引用
    bVC *bvc = [[bVC alloc] initWithNibName:NSStringFromClass([bVC class]) bundle:nil];
    // 不会循环引用
    // 当bvc被pop或者dismiss时 block也销毁了,因此当本VCdismiss时不存在被循环引用
    bvc.blcok = ^(NSString * _Nonnull str) {
        // 逆向传值
        self.label.text = str;
    };
    [self presentViewController:bvc animated:YES completion:nil];

会造成循环引用的情况,自己创建,引用自己
解释都在demo中了

typedef void(^Block)(void);
@interface BlockVC ()
@property (copy, nonatomic) Block myBlock;
/*+=============造成循环引用情况==============**/
    self.myBlock();
    
    
       __weak typeof(self) weakSelf = self;
    _myBlock = ^{
        // self持有block,block持有self。
//        NSLog(@"%@",self.view);
        // 此时解决了循环引用,但是,需要在__strong一次,
        __strong typeof(weakSelf) strongSelf = weakSelf;
        // 原因: 存在有一种场景,在block执行开始时self对象还未被释放,
        // 而执行过程中,self被释放了,此时访问self时,就会发生错误。
        NSLog(@"%@",strongSelf.view);
    }; 

三:UITableView

@interface TestTableViewCell : UITableViewCell
@property (nonatomic, strong) UITableView *tableView; // strong 造成循环引用
@end

// datasource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TestTableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:@"UITableViewCellIId" forIndexPath:indexPath];
    cell.tableView = tableView;
    return cell;
}

strong 改为 weak
@property (nonatomic, weak) UITableView *tableView; // strong 改为 weak

** 四: delegate**

@property (nonatomic, weak) id <MyDelegate> delegate;

测试Demo,可自行下载

上一篇 下一篇

猜你喜欢

热点阅读