iOS开发,为避免循环引用有时我们会在block里使用weakSelf

无敌鲨鱼炮
  • 448

那么什么时候我们需要将weakSelf改为strong??
希望有经验的同学结合实例说明一下。?
提前感谢了。

回复
阅读 3.4k
4 个回答
✓ 已被采纳

用__strong是为了保证对象在block执行前不被释放.
Demo: A 控制器(present)跳转到B, B dismiss回来.block里面有延时操作.

  1. 使用没__strong时, 在B控制器dismiss, secondVC释放为nil, 1.0秒后block执行, 此时weakVC为nil.

  2. 使用__strong, 调用dismiss, 由于block有强引用, secondVC不被释放(不是nil), 1.0秒后执行完block, 释放vc.

A控制器代码:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    SecondViewController *secondVC = [SecondViewController new];
    
    __weak SecondViewController *weakVC = secondVC;
    
    secondVC.secondBlock = ^(){
        
//        // 在SecondViewController界面调用dismiss后,依然可以正常输出, VC dealloc
//        __strong SecondViewController *strongVC = weakVC;
//        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//            NSLog(@"%@",strongVC.view);
//        });
        
        // SecondViewController调用dismiss后被释放为nil, 打印为nil
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",weakVC.view);
        });
    };
    
    [self presentViewController:secondVC animated:YES completion:nil];
}

B控制器代码:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.secondBlock();
    [self dismissViewControllerAnimated:YES completion:nil];
}

测试结果:
图片描述
图片描述

这个文章

一般不需要转成strong,或者在block中首先转成strong,然后再用。

检测代码中是否存在循环引用问题,可使用 Facebook 开源的一个检测工具 FBRetainCycleDetector

一般在block块内直接这样写没错

__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
   // ...
}

你可可以使用宏定义写法weakify strongify, 可参考http://www.jianshu.com/p/3d6c...

可以看看AFN的处理:weak strong dance,在block中,转为strong确保在执行block时,不会被释放。因为weak的生命周期更长,block执行完后,会转为weak。

 __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }

    };
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏