时间:2021-05-20
Block概述
Block它是C语言级别和运行时方面的一个特征。Block封装了一段代码逻辑,也用{}括起,和标准C语言中的函数/函数指针很相似,此外就是blokc能够对定义环境中的变量可以引用到。这一点和其它各种语言中所说的“闭包”是非常类似的概念。在iOS中,block有很多应用场景,比如对代码封装作为参数传递。这在使用dispatch并发(Operation中也有BlockOperation)和completion异步回调等处都广泛应用。
block对变量的捕获
1:可以捕获不可以修改变量
2:可以捕获且可以修改变量
原理分析:
1. 局部变量为什么可以被捕获确不能修改
int a = 10;void (^blcok)() = [^{ NSLog(@"%d",a);} copy];a=20;blcok(); // log : a = 10结果应该大家都知道,但是为什么会这样呢?
我们用clang转化之后看看
从block定义来看
block的实现是通过__ZMX__blockTest_block_impl_0结构体的构造方法来定义的,我们来看下这个结构体
impt:
isa:指向Class的指针
flags:一些标识
reserced:保留的一些变量
funcptr:函数指针
__ZMX__blockTest_block_desc_0:
reserced:保留的一些变量
size:内存大小
__ZMX__blockTest_block_impl_0 构造方法
我们可以看到这个构造方法有四个参数
我们通过简化block的定义:
可以看到,我们在定义的时候就已经将a作为参数传递进去了。也就是在定义的时候我们的block就获取到了a的值,而且不管后面怎么修改a的值。我们在block内部获取的a都是定义的时候传进来的值,这也就导致为什么block可以捕获局部变量却不可以修改的原因
2.1 全局变量 可以被捕获也可以修改
(void)blockTest{ void (^blcok)() = [^{ NSLog(@"%d",a); } copy]; a = 20; blcok(); // log : 20 }我们用clang转化之后看看
一样的部分我就不重复了,我们可以看到这个时候定义blcok的构造函数是没有传入之前的参数a
我们调用NSLog函数 = 上面__ZMX__blockTest_block_func_0函数
很显然,在我们调用block的时候,如果你之前有修改a的值,那打印的一定是新值
2.2 静态变量 可以被捕获也可以修改
(void)blockTest{ static int a = 10; void (^blcok)() = [^{ NSLog(@"%d",a); } copy]; a = 20; blcok(); //log : 20 }我们用clang转化之后看看
通过构造函数我们可以看到,这时候入参多了一个int *_a,传递的是a的地址了。打印的函数__ZMX__blockTest_block_func_0也一样,都是获取到同一内存地址上的值操作。so,我们既可以访问a同时也可以修改a了
2.3 __block修饰的变量 可以被捕获也可以修改
(void)blockTest{ __block int a = 10; void (^blcok)() = [^{ NSLog(@"%d",a); } copy]; a = 20; blcok();// log : 20 }我们用clang转化之后看看
哎!这时候的结构体__ZMX__blockTest_block_impl_0的a变成了一个结构体指针。好奇怪,我们来看一下这个结构体
我们再来看一下 我们blockTest函数
这时候变量a变成了一个__Block_byref_a_0结构体,可以看到我们初始化的时候给a的地址跟a的值都传进去了
再次赋值我们是通过修改a指向的内存地址上的value来修改a的值
打印函数
我们是通过先获取block捕获到的a的内存地址对应的value,然后打印出来
所以我们可以捕获并且修改a的值
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
C++中的虚析构函数到底什么时候有用的,什么作用呢。一.虚析构函数的作用总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也
最近学习《Python参考手册》学到Class部分,遇到了类的构造析构部分的问题:1、什么时候构造?2、什么时候析构?3、成员变量如何处理?4、Python中的
析构函数:当某个对象成为垃圾或者当对象被显式销毁时执行。GC(GarbageCollector)在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PH
我们在PHP中经常用到魔术方法,像构造方法,析构方法等等魔术变量,下面总结一下一些常用的魔术变量:__construct(),__destruct(),__cl
析构函数用于析构类的实例。备注不能在结构中定义析构函数。只能对类使用析构函数。一个类只能有一个析构函数。无法继承或重载析构函数。无法调用析构函数。它们是被自动调