iOS之常见循环引用

  • 循环引用:(大家都知道我们OC内存管理采用引用计数机制,可自行了解)A->B , B->A ,导致无法释放就造成了循环引用

我们怎么检查循环引用呢,比较简单的是当我们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中解释

  • 创建timer
  • 介绍Timer的常见方法
  • 如何解决循环引用


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

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

截屏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

  • 当我们使用cell时,cell 中的 strong 引用会造成循环引用。
@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;
}

  • 解决: 假如你用xib就知道拖出来时weak。
strong 改为 weak
@property (nonatomic, weak) UITableView *tableView; // strong 改为 weak

** 四: delegate**

  • 声明dellegate
@property (nonatomic, weak) id <MyDelegate> delegate;
  • 如果将weak改为strong,则会循环引用

测试Demo,可自行下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。