block分类
NSGlobalBlock
(全局block)
- 全局区
- 在block内部不实用外部变量,或者只使用静态变量和全局变量 代码:
static int a = 0;
void (^block)(void) = ^{
NSLog(@" %d",a);
};
NSMallocBlock
(堆区block)
- 堆区
- 在block内部使用变量或者OC属性,并且赋值给强引用或者Copy修身的变量 代码:
int a = 0;
void (^block)(void) = ^{
NSLog(@" %d",a);
};
NSStackBlock
(栈区block)
- 栈区
- 在block内部使用变量或者OC属性,但是不能赋值给强引用或者Copy修身的变量,也就是弱引用修饰。 代码:
int a = 10;
void ( __weak ^block)(void) = ^{
NSLog(@" %d",a);
};
block循环引用
- 为什么会产生循环引用?
A和B正常释放:
A强持有B,B强持有A,无法释放
- block循环引用案例
当我们采用上面的代码时候,就会出现循环引用。编译器也会提示 那么如何解决呢?
- 使用弱引用__weak
但是还有一个问题,当我们block是一个耗时操作,这个时候我们又退出页面,就会发现name为空。因为这个时候controller已经释放,那么如何解决这个问题
- 使用弱引用__weak + __strong
这个时候,有这样的应用关系self->block->weaSelf->strongSelf->Self
.因为strongself是一个临时变量,需要block执行完成后会销毁。这样既能打破循环,又能避免提前释放。
- 手动释放
self -> block -> vc -> self
,我们可以通过一个中间变量手动释放,当block执行完成后,把vc=nil,这样就可以打破循环
- block传参
我们知道OC的方法都默认有一个self参数,同样block我们也可以通过传入参数这种方式,避免出现循环引用。
block案例分析
案例一
:
static ViewController *staticSelf_;
- (void)blockWeak_static {
// 是同一片内存空间
__weak typeof(self) weakSelf = **self**;
staticSelf_ = weakSelf;
// staticSelf_ -> weakSelf -> self
}
上面的代码是否会产生循环应用?答案是会产生。
首先我们分析staticSelf_ -> weakSelf -> self
,staticSelf_
是一个全局静态变量,退出界面后不会释放。所以导致self不会释放。所以__weak不一定不会导致内存泄漏。
案例二
:
上面的代码也会产生内存泄漏,strongSelf被dostudent持有,导致strongSelf无法释放。self->weakSelf->strongSelft->doStudent->WeakSelf.