iOS 面试

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

2017-05-24  本文已影响31人  XDLee

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步。

上一篇下一篇

猜你喜欢

热点阅读