Block
是在栈上生成的,因此通常使用copy
方法把Block
复制到堆上,避免Block
被马上释放。spa
Block
会对内部的变量造成强引用,而若是同时该变量又持有这个Block
,就会致使循环引用而没法释放,从而致使内存泄露。code
最多见的就是self
持有Block
,而又在Block
内部调用self
的方法或属性,那self
和Block
就会造成循环引用而没法释放。因为咱们习惯在dealloc
中释放对象,可是即便在dealloc
中将Block
释放也没用,由于self
的dealloc
根本不会跑进去。好比:对象
1 self.MyBlock = ^void(){ 2 3 [self doSomething]; 4 };
其实,最简单的解决方法就是在self
的某个非dealloc
方法中将Block
主动释放,并在须要释放self
以前调用这个方法,这样才能有效的解除引用。可是这种方法使用起来比较麻烦,并且很容易忘记调用。blog
因此咱们通常是在Block
中使用弱引用的self
。下面分别介绍ARC
和MRC
中在Block
中使用弱引用self
的方法。内存
1 __weak typeof(self) weakSelf = self; 2 3 self.MyBlock = ^void(){ 4 5 __strong typeof(self) strongSelf = weakSelf; 6 7 [strongSelf doSomething]; 8 };
这样作的好处是没必要在Block
直接使用self
,这样就不会对self
进行强引用,只要self
须要释放,self
就会自动释放,Block
也会自动释放。在ARC
中,进入Block
前,须要使用__weak
对self
进行弱引用,并在Block
中使用__strong
对weakSelf
进行强引用。开发
这样作的另外一个好处是,在ARC
中使用__weak
以后,若是self
在某个地方被释放了,那weakSelf
也会被自动置为nil
,这样即便在Block
中使用weakSelf
,也不会访问错误。get
而在Block
中使用__strong
则是为了不在使用Block
的过程当中self
被释放致使访问出错。class
1 __block typeof(self) blockSelf = self; 2 3 self.MyBlock = ^void(){ 4 5 if (!malloc_zone_from_ptr(blockSelf)) 6 return; 7 8 __strong typeof(self) strongSelf = blockSelf; 9 10 [strongSelf doSomething]; 11 };
其实,MRC
的基本思路和ARC
是同样的。有两处不一样:变量
在MRC
中使用__block
而不是__weak
进行弱引用,由于在ARC
中使用__block
会对该对象进行强引用。循环
在MRC
的Block
中使用malloc_zone_from_ptr()
方法判断blockSelf
是否已经被释放,由于MRC
不会对已释放的对象自动置为nil
。
可见,不管是MRC
仍是ARC
,解决方法都是相似的。虽然Block
的使用增长了简洁性和便利性,但使用Block
的过程当中也要时刻注意避免内存泄露。
How Do I Declare A Block in Objective-C? 总结了声明Block
的几种格式,在开发过程当中能够参考使用。