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从栈上复制到堆上的代码。由于其被复制到了堆上,可以常驻内存,因此仍然在存活的声明周期内。
  • 需要手动将Block从栈复制到堆上的情况(编译器不能进行判断,又不能无脑使用copy【耗性能】)
    • 向方法或函数的参数中传递Block时
  • 在ARC环境下,编译器会根据情况自动将栈上的Block复制到堆上(比书上多2种)
    • Block作为函数返回值时;这就类似与MRC中对返回值Block执行了[[returnedBlock copy] autorelease];
    • Block被强引用,如Block被赋值给__strong或者id类型;
    • Block作为GCD API的方法参数时;
    • Block作为系统方法名含有usingBlock的方法参数时;

4. 参考资料

原文地址:https://www.cnblogs.com/HelloGreen/p/12854076.html