跟大家讲一讲MRC和ARC下属性Block的循环引用问题
最近有个朋友看了我的博客,吐槽说,能不能发一些基础性的教学之类的,说实话,基础性的一些东西我虽然记得,但是你叫我总结的话我真的总结不出来,现在唯一能做的就是如果平时想到哪些以前遇到的一些Bug比较让我觉得有意思的话,我就把他给写出来了,
刚开始学iOS的人必定会被他的循环引用所烦死,最烦的莫过于属性Block的循环引用问题,我这写了一下关于MRC和ARC下的循环引用问题;
typedef void(^Block)();
@interface ViewController ()
@property (nonatomic, copy)Block block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//// 1.未加__block的时候
// NSLog(@"最初的self.retainCount_%ld",self.retainCount);
// //打印: 最初的self.retainCount_3
// UIViewController *weakSelf = [self retain];
// NSLog(@"&weakSelf__%p__self.retainCount__%ld",&weakSelf,self.retainCount);
//
// //&weakSelf__0x7fff56402ab8__self.retainCount__4
//
// //block一旦实现则存储在堆区,则也相当于一个对象
// self.block = ^(){
// weakSelf.view.backgroundColor = [UIColor redColor];
// //block里头的weakSelf成为了野指针,且引用计数增加
// NSLog(@"Block里头&weakSelf__%p__self.retainCount__%ld",&weakSelf, weakSelf.retainCount);
// //打印:Block里头&weakSelf__0x7fa393d43080__self.retainCount__5
// };
// self.block();
//
// NSLog(@"&weakSelf____%p__self.retainCount__%ld",&weakSelf,self.retainCount);
//
// //&weakSelf____0x7fff56402ab8__self.retainCount__5
//
// //即使release之后,self.retainCount也只是回到4,并没有回到3
// [weakSelf release];
//
// 加了__block之后;
NSLog(@"最初的self.retainCount_%ld",self.retainCount);
//打印: 最初的self.retainCount_3
__block UIViewController *weakSelf = [self retain];
NSLog(@"&weakSelf__%p__self.retainCount__%ld",&weakSelf,self.retainCount);
//打印&weakSelf__0x7fff57762ab8__self.retainCount__4
//block一旦实现则存储在堆区,则也相当于一个对象
self.block = ^(){
weakSelf.view.backgroundColor = [UIColor redColor];
//因为加了__block即使拷贝了新的一份,也导致引用计数也不会增加
NSLog(@"Block里头&weakSelf__%p__self.retainCount__%ld",&weakSelf,weakSelf.retainCount);
//打印 &weakSelf__0x7f8392c1aeb8__self.retainCount__4
};
self.block();
NSLog(@"&weakSelf____%p__self.retainCount__%ld",&weakSelf,self.retainCount);
//此时&weakSelf是真的改变了
//&weakSelf____0x7f8392c1aeb8__self.retainCount__4
[weakSelf release];
//引用计数回到初始值3;
}
MRC的属性block的循环引用问题综算解决了,但是问题又来了既然加了__block可以解决问题,那么为什么不能够在ARC状态下写__block呢?
原因很简单,因为在ARC下,由于__block抓取的变量一样会被Block retain,所以必须用弱引用才可以解决循环引用问题,iOS 5之后可以直接使用__weak,之前则只能使用__unsafe_unretained了;
好了,大概就讲完了,大家好好消化吧;