您的位置:首页 > 其它

block深入学习

2015-08-09 14:22 274 查看
block的声明和使用看上一节就行了。

本章主要讲block内部的实现过程及原理。block的定义和函数指针非常相似

对比一下

block定义
void (^someBlock)() = ^{//       };

函数指针定义

void (*functionPionter)() = void functionName(){

//内部定义

}


当然区别还是有的,block的返回类型可以省略,在block块的结尾有分号。

block也能捕获对象类型,就是在块中使用实例变量。块本身也可以视为对象。对于实例变量,前面不加__block,也能改变其值。



块的内部结构

块的底层可以说是函数指针,当然,里面还有其它信息。



这是内部结构图。块本身也是对象,在存放块对象的内存区域中,首个变量是指向Class对象的指针,该指针叫isa。和object中的isa是一个意思。

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

在定义块的时候,其中所占的内存区域是分配在栈中的,这就是说,块只在定义它的那个范围内有效,像下面的这种情况就会出现危险。



定义在if及else语句中的两个块都分配在栈内存中。编辑器会给每个块分配好栈内存,然后等离开了相应的范围之后,编辑器有可能把分配给块的内存覆盖掉。块在if中有效,但是运行起来,时而正确,时而错误。

为了解决此问题,可以给对象发送copy消息以拷贝,就把块从栈复制到堆内存了,就可以在定义它的范围之外使用。然后块就成带有引用计数的对象了。所以给代码加上两个copy方法调用,就可以解决此问题了。



当然了,除了“栈块”和“堆块”之外,还有一类块叫做“全局块”(global block)。这种块不会捕捉任何状态,运行时也无须有状态来参与。块所使用的整个内存区域,在编译期已经完全确定了,因此,全局快可以声明在全局内存里,全局域不可能被系统所回收。这种块相当于单例。下面就是全局快:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: