本文章主要是对block本质的进行探讨和研究做如下笔记。主要通过以下几个知识点为突破口进行学习:
- block的本质;
- block的变量捕获;
- block类型;
一、block的本质
blcok的本质是结构体(__main_block_impl_0)也是一个oc对象(有isa指针)。具体如下;
struct __main_block_impl_0{
struct __block_impl impl;
struct __main_block_desc_0 * Desc; //block描述信息
... //捕获的其他的成员变量
}
struct __block_impl{
void *isa;
int Flags;//默认为0
int Reserved;
void * FuncPtr;//指向函数的地址
}
struct __main_block_desc_0 {
size_t reservd;//默认为0
size_t Block_size;// __main_block_impl_0 的占用内存大小
void (*copy)(struct __main_block_impl_0,struct __main_block_impl_0);
void(* dispones)(struct __main_block_impl_0)
}
二、关于变量捕获(capture)
到外部的变量在block代码块使用时,block在构造函数会生成一个通类型的同名称的成员变量,并且在构造函数输入传入赋值。
block的捕获机制:
- 局部变量 auto 通过值传递;
- 局部变量 static 通过指针传递;
- 全局变量 不会捕获到 __main_block_impl_0 内部,block 函数直接访问。
局部的自动变量会随时销毁,但是static的指针地址会一直在内存。
全局变量没有作用域谁都可以访问,也就是说函数可以直接访问,不用捕获到block内部,也就是说在__main_block_impl_0 不会生成全局变量成员。
三、block类型。
block本质是结构体但是也是一个oc对象最终是集成NSObject,其isa就是NSObject的指针。
主要类型分为三种:
- NSGlobalBlock
- NSStackBlock
- NSMallocBlock
具体的区别:
block 调用copy后的变化情况:
栈和堆的数据区别: 栈的离开作用域后,数据会销毁;而堆则不会,除非调用release操作。
总结:
block需要注意的就是:变量捕获和类型对应的值的引用。