OC对象 - Block的类型
1. Block有三种类型
- 全局:
__NSGlobalBlock__( _NSConcreteGlobalBlock ) - 栈区:
__NSStackBlock__( _NSConcreteStackBlock ) - 堆区:
__NSMallocBlock__( _NSConcreteMallocBlock )
1.1 它们最终都是继承自NSBlock,NSBlock则是继承自NSObject
1.2 它们位于程序的不同内存区域

2. 不同类型的Block
2.1 特点
| block类型 | 环境 |
|---|---|
| NSGlobalBlock | 没有访问auto变量 |
| NSStackBlock | 访问了auto变量 |
| NSMallocBlock | __NSStackBlock__调用了copy |
2.2 每一种类型的block调用copy之后

3 验证
3.1 打印black类型
我们逐级打印black的class、superclass,可以看到最终是继承自NSBlock,NSBlock则是继承自NSObject
3.1 验证不同类型的Block
我们已经知道,访问了auto变量的block是NSStackBlock类型,__NSStackBlock__调用了copy后是NSMallocBlock
当运行如下代码,却发现访问了 auto 变量的 block 却是__NSMallocBlock__

3.2 ARC和MRC
这是因为,现在项目默认是启用ARC的,ARC下会自动帮我们添加copy操作(具体规则后面章节讲),我们先把项目设置为MRC
重新运行
和我们预期的一样
4. block的copy
4.1 在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况
- block作为函数返回值时
- 将block赋值给__strong指针时
- block作为Cocoa API中方法名含有usingBlock的方法参数时
- block作为GCD API的方法参数时
4.1.1 block作为函数返回值时
通过下面示例,验证了block作为函数返回值时是__NSMallocBlock__,直接创建打印则是__NSStackBlock__

4.1.2 将block赋值给__strong指针时
- 创建
ZSXPerson类,并声明一个strong修饰的block属性
@interface ZSXPerson : NSObject
@property (strong, nonatomic) void (^block)(void);
@end
- 初始化
ZSXPerson实例对象person,并把block赋值给person.block
此时的 block 是__NSMallocBlock__
4.1.3 block作为Cocoa API中方法名含有usingBlock的方法参数时
示例:

4.1.4 block作为GCD API的方法参数时
示例:

4.2 MRC下block属性的建议写法
@property (copy, nonatomic) void (^block)(void);
4.3 ARC下block属性的建议写法
@property (strong, nonatomic) void (^block)(void); @property (copy, nonatomic) void (^block)(void);
@oubijiexi