IOS使用Block —— 3 Block的两个注意点
首先普及一下内存存储区域知识:
内存分为五大区域:堆、栈、全局区、文字常量区、代码区
堆存放:由new、alloc分配的内存块,由程序员控制释放 p1 = (char *)malloc(10);
栈存放:存放函数参数、局部变量,在不需要的时候由编译器自动清除的变量存储区。 int b; char s[] = “abc”; char*p2;
全局区(静态):全局变量和静态变量存储放在一块的,程序结束后由系统释放
文字常量区:常量字符串放在这里,程序结束系统释放
代码区:存放函数体的二进制代码
1 block在MRC下的内存隐患
问题:
1 - 下面这段代码在ARC中是否存在问题?
不存在
2 - 下面这个代码在MRC中是否存在问题?
存在,设置block后,在合适的时间回调block,不希望block被释放,所以要对block进行copy
typedef void (^blockType)(); // 定义返回值是block类型的函数 blockType test() { int i = 5; blockType bb = ^{ NSLog(@“xxxx i = %d”, i); } // return bb; // 防止被释放,copy到堆区,所以需要改为 return Block_copy(bb); return Block_copy(bb); } int main() { @autoreleasepool { // 接收test的返回值 blockType b1 = test(); // 执行block b1(); // MRC下copy到堆区一份,需要释放该block的控件,所以需要添加一句 Block_release(b1()); Block_release(b1()); } }
2 block循环引用
发现问题:
控制器中对Block进行copy,copy后对block进行一个强引用,block中的self对控制器进行强引用,所以造成了一个强引用环,互相无法释放
![](https://images2015.cnblogs.com/blog/797058/201509/797058-20150903145817606-152615337.png)
解决问题:
打破强引用环只要将block中的 self 变成弱指针,即可解决;
// 这个神奇的方法就是: __weak typeof(self) weakSelf = self; // 将block中的self改为weakSelf
![](https://images2015.cnblogs.com/blog/797058/201509/797058-20150903151932122-1234228425.png)
最后本人在查阅过程中翻过的帖子贴上:
——————内存————————
堆栈区别:http://blog.csdn.net/aixiaolin/article/details/6863991
区域划分:http://blog.csdn.net/wealoong/article/details/8686353
——————block————————
ARC与非ARC下block属性问题:http://www.mgenware.com/blog/?p=1493
容易引起“循环引用”的三种场景:http://www.2cto.com/kf/201409/332193.html
block使用测试:http://www.cocoachina.com/bbs/read.php?tid=152222&page=1