美文网首页iOS 面试
Block循环引用的两种情况(self和私有成员变量)

Block循环引用的两种情况(self和私有成员变量)

作者: XDLee | 来源:发表于2017-05-24 20:33 被阅读31次

    Block的循环引用问题非常常见

    1、Block 内部引用 self,造成循环引用

    (1)这种 Block 循环引用最为常见,以下代码中的 self(控制器)无法释放

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, copy) void(^demoBlock)();
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
       
        [self blockDemo1];
    }
    
    #pragma mark - block 内部使用 self, 造成的循环引用
    - (void)blockDemo1 {
        
        self.demoBlock = ^{
            self.name = @"Jack";
        };
    }
    
    - (void)dealloc {
        NSLog(@"%s", __FUNCTION__);
    }
    

    (2)解决办法

    1> 在 Block 外部加上 __weak typeof (self) weakSelf = self; 
    2> 在 Block 里面使用 weakSelf.属性 就ok了。
    只需做到这两步就可以解决循环引用。
    

    (3)代码如下

    #pragma mark - block 内部使用 self, 造成的循环引用
    - (void)blockDemo1 {
        
        __weak typeof(self) weakSelf = self;
        self.demoBlock = ^{
            weakSelf.name = @"Jack";
        };
    }
    

    2、Block 内部引用私有成员变量,造成的循环引用

    (1)_成员变量 默认是 __strong 修饰的,Block内部直接引用 _成员变量,就会造成循环引用

    #import "ViewController.h"
    
    @interface ViewController () {
        NSMutableArray *_nameList;
    }
    
    @property (nonatomic, copy) void(^demoBlock)();
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
       
        [self blockDemo2];
    }
    
    #pragma mark - block 内部使用私有成员变量,造成的循环引用
    - (void)blockDemo2 {
       
        self.demoBlock = ^ {
            [_nameList addObject:@"Jack"];
        };
    }
    
    - (void)dealloc {
        NSLog(@"%s", __FUNCTION__);
    }
    

    (2)解决办法

    1> 在 Block 外部加上 __weak typeof (self) weakSelf = self; 
    2> 在 Block 内部必须加上 __strong typeof(weakSelf) strongSelf = weakSelf;
    3> 最后,使用 strongSelf->_成员变量 来处理。
    注意: 第2步不能少。
    

    (3)代码如下

    - (void)blockDemo2 {
        
        __weak typeof(self) weakSelf = self;
        self.demoBlock = ^ {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            [strongSelf->_nameList addObject:@"Jack"];
        };
    }
    

    如果没有第2步,就会报以下错误

    错误信息.png

    因此,必须加上第2步。

    相关文章

      网友评论

      本文标题:Block循环引用的两种情况(self和私有成员变量)

      本文链接:https://www.haomeiwen.com/subject/gfioxxtx.html