Block存储域学习
更新记录
时间 | 版本修改 |
---|---|
2020年5月9日 | 初稿 |
2020年5月10日 | 添加编译器不能自动将Block从栈复制到堆上的情况说明 |
1. 前言
- 本文主要参考了《Objective-C高级编程 iOS与OS X多线程和内存管理》2.3.4节 Block存储域的内容,也可以直接阅读该书籍,会更加原汁原味。
- 我试图从网上找一下《Objective-C高级编程 iOS与OS X多线程和内存管理》2.3.4节的图,发现竟然一张都没找着,本来还想贴一下图的,本人虎躯一震,一切图片都变得索然无味。
- 所以我建议还是直接看《Objective-C高级编程 iOS与OS X多线程和内存管理》2.3.4节比较好,高清无码。。。
2. Block存储域的分类
- Block为全局Block的情况
- 声明全局变量的地方有Block语法
- Block语法的表达式中不捕获自动变量时(不同编译器可能实现不一样,都是都可以做成这样,因为不捕获自动变量,放在全局区是没有问题的)
- Block为栈Block的情况
- 普通声明局部Block局部变量
- Block为堆Block的情况
- 调用copy函数,将栈Block复制到堆Block
3. Block从栈上自动复制到堆
- 为什么Block超出其作用域仍然可存在?
- 在ARC大多数情况下,Block栈变量会被编译器自动地进行判断,生成将Block从栈上复制到堆上的代码。由于其被复制到了堆上,可以常驻内存,因此仍然在存活的声明周期内。
- 在ARC大多数情况下,Block栈变量会被编译器自动地进行判断,生成将Block从栈上复制到堆上的代码。由于其被复制到了堆上,可以常驻内存,因此仍然在存活的声明周期内。
- 需要手动将Block从栈复制到堆上的情况(编译器不能进行判断,又不能无脑使用copy【耗性能】)
- 向方法或函数的参数中传递Block时
- 在ARC环境下,编译器会根据情况自动将栈上的Block复制到堆上(比书上多2种)
- Block作为函数返回值时;这就类似与MRC中对返回值Block执行了[[returnedBlock copy] autorelease];
- Block被强引用,如Block被赋值给__strong或者id类型;
- Block作为GCD API的方法参数时;
- Block作为系统方法名含有usingBlock的方法参数时;
4. 参考资料
- 《Objective-C高级编程 iOS与OS X多线程和内存管理》2.3.4节
- 《Block原理探究(上篇)-Block本质及存储域问题》