关于 block
- block 实质
对闭包的实现。闭包(可以访问局部变量的匿名函数)(局部变量指实现该闭包的作用域的变量)
block 基础:
声明实现格式 前半部分 block 的声明,后半部分 block 的实现
return_type (^ block_name) (id parameterOne, id parameterTwo) = ^ (id parameterOne , id parameterTwo) {};
- block 获取局部变量 (捕获外部局部变量,不能修改栈中指针指向位置)
默认操作外部变量的规则
可以读取外部变量的值,不可以写外部变量的值 (能读不能写)
注:block捕获的是定义block中时候,局部变量的只读拷贝,即定义时间点的变量的值
(此处的外部变量指的是栈中指针的内存地址
对于基本数据类型,即不能改变该变量的值
对于OC对象,即不能改变该指针的指向,可以修改其属性值)
为什么设计为这样的规则?
block 本质上还是一个匿名函数。进入该函数后标识这作用域的改变。
为了保证变量维护的方便性,所以设置可以访问外部变量,但不能改变外部变量的值
(系统如何限制不允许修改栈区 内存地址的指向?)
如何改变外部变量的值?
使用__block进行修饰,将栈区中的内存挪到堆区中。
规避了block中的规则,可以对数据进行修改。
可以进行任意的修改。在出了block作用域后,使用的是堆区的内存
-
block 对实例变量的捕获
在block中捕获实例变量,由于实例变量是和self绑定,所以其也捕获了self。由于写法中没有突出,所以经常导致忘记这一事实 -
栈块、区块、全局块
a:全局块,在全局作用域中定义的块。在编译器确定布局。不会捕获任何的实例变量。 相当于一个单例。 对他的拷贝操作是空操作。
b:栈块,定义在某个作用域内的块对象
c:区块,如经过set方法,函数参数传递的(经过了作用域改变的)块,经过copy操作将block从栈区拷贝到了堆区 -
block中的引用循环
block中很容易造成引用循环导致内存泄露。
对于self,通过外部捕获weak引用,内部添加strong引用,规避引用循环
网友评论