关于block循环引用的问题

来源:互联网 发布:ubuntu输入法 编辑:程序博客网 时间:2024/06/05 15:17

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】



原创粉丝点击