关于block循环引用的问题

1.首先来看典型的block循环引用

#import "ViewController.h"

@interface ViewController ()
@property (copy,nonatomic) void (^printBlock)();
@property (copy,nonatomic) NSString *name;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.name=@"wall";
    self.printBlock=^(){
        NSLog(@"%@",self.name);
    };
    self.printBlock();
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

分析:这是典型的循环引用,如下图所示:self强引用printBlock,而printBlock也强引用self

2.解决办法

#import "ViewController.h"

@interface ViewController ()
@property (copy,nonatomic) void (^printBlock)();
@property (copy,nonatomic) NSString *name;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.name=@"wall";
    __weak typeof(self)weakSelf=self;
    self.printBlock=^(){
        typeof(weakSelf)strongSelf=weakSelf; //使用弱引用的外部变量weakSelf
        NSLog(@"%@",strongSelf.name);
    };
    self.printBlock();
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end


分析:由于weakSelf是弱引用指针,即代码块使用的是弱引用外部变量,所以printBlock弱引用self,用虚线箭头表示,self任然强引用printBlock,此时并没有形成循环引用。还有非常重要的一点需要注意,就是为什么代码块内打印name值的时候,使用的是strongSelf?这是因为,如果使用weakSelf,当ViewController对象被释放的时候,weakSelf=nil,再使用weakSelf是无效的,而使用strongSelf就可以解决这个问题。但是有人可能会问,这样的话,不是又循环引用了吗?尤其是看下面这张图。其实这样并不是循环引用,因为strongSelf是在代码块内部定义的,属于代码块局部变量,代码块使用完后就会被释放,所以就不存在所谓的循环引用。



补充:

(1)如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】

(2)如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】



猜你喜欢

转载自blog.csdn.net/chokshen/article/details/72692344