iOS底层原理 - block如何修改外部变量
2021-03-20 本文已影响0人
欧币杰昔
在block里面需要修改外部变量时,我们会使用__block修饰这个外部变量,然后再对其进行修改操作,这是为什么呢?
今天将使用clang编译.c文件,来看看block是怎么实现修改外部变量的
首先,我们看下block声明后是怎样的
main.c
#include <stdio.h>
int main(int argc, const char * argv[]) {
void(^block)(void) = ^{
printf("Hello block!\n",);
};
block();
return 0;
}
main.cpp
image.png
block本质是个OC对象,看到结构体里面也有个isa指针了吗。他的构造方法传入一个函数并存储到FunncPtr,然后在block()的时候就会执行这个函数
我们访问一下外部变量看看:
main.c
#include <stdio.h>
int main(int argc, const char * argv[]) {
int a = 1;
void(^block)(void) = ^{
printf("Hello block!a=%d\n",a);
};
block();
return 0;
}
main.cpp
image.png
此时结构体中多了个变量a,以这样的方式保存捕获到的外部变量。
步骤2可以看到,对cself->a做了值拷贝操作,所以此时可以访问外部变量a,但是无法修改
我们用__block修饰一下外部变量看看:
main.c
#include <stdio.h>
int main(int argc, const char * argv[]) {
__block int a = 1;
void(^block)(void) = ^{
printf("Hello block!a=%d\n",a);
};
block();
return 0;
}
main.cpp
image.png
这时候主要区别在于,他把外部变量a捕获到一个结构体中,因为结构体是在堆区的,这样a就不会出了作用域就销毁。同时捕获了结构体a的指针地址,然后在block里面操作的也是就a的指针地址,所以就达到了修改的目的。
今天先分享到这。
如发现分析得不对、不合理的地方,欢迎提出讨论~