myBlk clang后转换为 Blcok的结构体类型的自动变量框架
__block 变量a clang 后转换成 __block变量的结构体类型的自动变量async
_NSConcreteStackBlock 栈函数
_NSConcreteGlobalBlock 全局区(静态区) 准确说是 .data区 .data区是放已被初始化的全局、静态)spa
_NSConcreteMallocBlock 堆设计
没有引用自动变量的block叫作NSGlobalBlock, (引用全局或者外部变量仍是NSGlobalBlock)对象
其他Block生成的Blcok 为 NSStackBlock类对象, 且设置在栈区资源
这正是上一篇博客留下的问题:Blcok 超出变量做用域可存在的缘由?作用域
配置在栈区的Block, 其做用域结束时,该Block就被废弃了。 __block 也是配置在栈区,做用域结束时一样也会被废弃。博客
全局区的block 做用域广,因此不会有这种问题,可是全局Block 是不捕获自动变量的。用的也少。it
那怎么解决栈区Block 过了做用域销毁的问题呢?
Blocks 提供了将Block 和 __block变量 从栈上 复制到 堆上 的方法 来解决这个问题。将栈上的Blcok 复制到堆上,这样即便Block的变量做用域结束了,堆上的Block还能够继续存在。
这就解决了过了做用域销毁的问题
在看__forwarding 的问题, __block变量用结构体成员变量__forwarding能够实现不管__block变量配置在栈上仍是堆上,都能正确的访问__block结构体变量。
栈区block copy 后从栈区到堆区
全局block copy 后什么也不作
堆区block copy 后引用计数增长
因此 无论Block配置在何处,用copy都不会引发任何问题。可是copy是至关消耗CPU资源的,当Block在栈区可使用时,就不要copy进堆区。
且在 ARC中屡次copy 也没有任何问题。 ARC中大部分状况系统都帮你作了copy,只有 向方法或函数的参数传递Block时,系统不会自动copy。 可是若是在方法或函数中适当地复制了传递过来的参数,就不用在调用方法或函数前手动复制了。好比有些方法就为咱们这么设计了:
1.cocoa框架的方法且方法名中含有usingBlock的方法
2.GCD 的API
具体举例:NSArray类的 enumerateObjectsUsingBlock 实例方法
GCD的 dispatch_async函数
都不须要手动复制。
须要手动复制的方法:
NSArray initWithObjects 实例方法上传递Block是须要手动复制
缘由是:block是栈区block 过了做用域,block就销毁了。
解决办法:将block 复制到堆区。