什么时候栈上的Block会被复制到堆呢?
1. 调用block的copy函数时;
2. Block作为函数返回值返回时;
3. 将Block赋值给附有__strong修饰符id类型的类或者Block类型成员变量时;
4. 方法中含有usingBlock的Cocoa框架方法或者GCD的API中传递Block时;
在 ARC 中,捕获外部了变量的 block 的类会是 __NSMallocBlock__ 或者 __NSStackBlock__,如果 block 被赋值给了某个变量在这个过程中会执行 _Block_copy 将原有的 __NSStackBlock__ 变成 __NSMallocBlock__;但是如果 block 没有被赋值给某个变量,那它的类型就是 __NSStackBlock__;没有捕获外部变量的 block 的类会是 __NSGlobalBlock__ 即不在堆上,也不在栈上,它类似 C 语言函数一样会在代码段中。
在非 ARC 中,捕获了外部变量的 block 的类会是 __NSStackBlock__,放置在栈上,没有捕获外部变量的 block 时与 ARC 环境下情况相同。