在平时的开发中我们经常使用block来传值和事件传递,但是block的使用很容易造成循环引用(我引用你 你引用我 就会造成循环引用),产生内存泄漏;
block很容易产生循环引用,跟执行或者不执行block无关。
只要是写了产生循环引用的代码,即使不执行,也会导致引用对象无法被释放,我们平时写block的生命属性的时候,会选择用copy或者是strong来使用,在MRC中我们会选择使用copy,在ARC中我们使用cop又或者使用strong都可以,最好使用还是strong因为copy的底层实现还是会进行一些判断,相比之后性能会差点。
-
全局对象引用Block,也会导致对象销毁不了
-
block:(捕获机制)会自动把block代码块中的强指针 强引用.
- 我们定义的局部的block引用self的属性,是不会造成循环引用的,因为self本身没有对我们的block强引用,所以没有造成闭环
- (void)viewDidLoad
{
[super viewDidLoad];
void (^block)(void) = ^{
self.age++;
NSLog(@"%d",self.age);
};
block();
}
- (void)dealloc
{
NSLog(@"dealloc");
}
- 如果我们用self引用我们的block那么会造成循环引用
/***********/
- (void)viewDidLoad
{
[super viewDidLoad];
void (^block)(void) = ^{
self.age++;
NSLog(@"%d",self.age);
};
_block = block;
}
/******如果我们呢把block里面的self.age改成_age,
同样还是会造成循环引用,因为他的本质还是会调用 self=>_age
******/
- 避免方法
如果我们在 定义一个weak使用的话就不会造成循环,
但是注意,如果block里面的操作有延时操作的话,不能直接使用weakSelf,
因为控制器有可能会销毁,这是再执行操作会造成拿不到数据
应该在里面再对这个弱指针强引用一次避免他提前销毁
void (^block)(void) = ^
{
// __strong typeof (weakSelf) strongSelf = weakSelf;
weakSelf.age = 90;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
{
NSLog(@"----%d",weakSelf.age);
//这时候的weakSelf已经是空的了,null
NSLog(@"----%@",weakSelf);
});
};
_block = block;
block();
//我们在block中使用要再加上这句话
__strong typeof (weakSelf) strongSelf = weakSelf;
里面使用strongSelf这样保证了self不会在执行延时操作之前被销毁
- 全局变量引用block也会造成循环
static void(^globalBlock)(void);
globalBlock = ^
{
NSLog(@"%ld", self.age);
};
网友评论