关于iOS Block当中为什么要用weakSelf和strongSelf的思考

时间:2021-07-07 15:34:38

  场景:当你在某个界面请求网络数据的时候,用户不愿意等待点击了返回按钮,此时在Block当中用如下的方式使用weakSelf的话,有可能会奔溃(因为在并发编程的情况下,虽然在if判断的时候weakself不为空,但是不保证if语句里面的weakself不为空),所以为了安全起见要加上strongSelf(参考)。

if (weakSelf != nil) {
       // last remaining strong reference released by another thread. 
       // weakSelf is now set to nil.
       [myArray addObject:weakSelf];
}

  那为什么加上strongSelf就可以保证self不为空了?

  因为如果self有效,那么strongself就是利用了循环引用的特性保证了在block执行的时候self对象不会被析构,strongSelf是局部变量执行完成后就会释放

 

  接下来用个Demo验证下,在FirstVC的ViewDidLoad里面添加以下代码

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.5* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.navigationController pushViewController:[SecondVC new] animated:NO];
    });
    
    //0.025 - 0.03
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.55 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.navigationController popViewControllerAnimated:NO];
    });

 

  然后在 SecondVC的 里面添加以下代码

  

typedef void(^TTestBlock)(int result);

@interface SecondVC ()
@property (strong, nonatomic)  TTestBlock  aBlock ;
@end

@implementation SecondVC

- (void)viewDidLoad {
    [super viewDidLoad];

    [self testForBlock];
}

- (void)testForBlock{
    
    __weak typeof(self) wSelf = self;
    self.aBlock = ^(int result) {
        
        NSLog(@"testForBlock:%@",wSelf);
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            
            //没有下面这一行的话,testForBlock2 中的self为空
            __strong typeof(wSelf) strongSelf = wSelf;
            
            NSLog(@"testForBlock1:%@",wSelf);

            [NSThread sleepForTimeInterval:1];

       //__strong typeof(wSelf) strongSelf = wSelf;  //放在这儿的话也wSelf会为空
            NSLog(@"testForBlock2:%@",wSelf);
        });
    } ;
    self.aBlock(0);
}
@end

 

 

注意:

  • 关于Masonry里面的Block:函数参数里面的Block是局部的block(栈上),block内部引用self不会造成循环引用;是否会循环引用只看函数内部是否copy了这个block(比如把它付给全局的Block)(参考
  • 关于IBOutlet的weak:因为xib里面的根视图已经强引用了拖拽上去的UI控件了,所以拖拽到VC里面用weak就行(参考
  • 关于weak的实现原理:Runtime维护了一个weak(hash)表,用于存储指向某个对象的所有weak指针;当对象的强引用计数为0的时候,会找到该对象的所有weak指针,将它置为nil。