block 块的内部结构

每个oc对象都占据着某个内存区域,因为实例变量的个数及对象所包含的关联数据互不相同,所以每个对象所占的内存区域大小也是有大有小,块本身也是对象,在存放块对象的内存区域中,首个变量是指向Class对象的指针,该指针叫做isa。其余内存里含有块丢向正常运转所需的各种信息。

                            如下:

void* isa
int flags
int reserved
void(*)(void,*..) invoke
struct* descriptor
捕获到的变量

                        下图为descriptor里的结构描述

块描述符
unsigned long int reserved
unsigned long int size
void (*)(void *,void*) copy
void(*)(void*,void*) dispose

 在内存布局中,最重要的就是invoke变量,这是个函数指针,只想块的实现代码,函数原型至少接受一个void*型的参数,此参数代表块。刚才说过,块其实就是一种代替函数指针的语法结构,原来使用函数指针时,需要用“不透明的void指针”来传递状态。而改用块之后,则可以把原来用标准C语言特性所编写的代码封装成简明且易用的接口。

descriptor变量是只像结构体的指针,每个块里都包含此结构体,其中声明了块对象的总体大小,还声明了copy与dispose这两个辅助函数所对应的函数指针。辅助函数在拷贝及丢弃块对象时运行,其中会执行一些操作,比方说,前者要保留捕获的对象,而后者将之释放。

块还会把它所捕获的所有变量都拷贝一份,这些拷贝放在descriptor变量后面,捕获了多少个变量,就要占据多少内存空间,请注意,拷贝的对象不是对象本身,而是指向这些对象的指针变量。invoke函数为何需要把块对象作为参数传进来呢?原因就在于,执行块时,要从内存中把这些捕获到的变量读出来。

这里只是帮助理解块对象的内部的结构,实际用处感觉不大。

原文地址:https://www.cnblogs.com/lingzhiguiji/p/4009218.html