iOS底层原理 - block如何修改外部变量

在block里面需要修改外部变量时,我们会使用__block修饰这个外部变量,然后再对其进行修改操作,这是为什么呢?
今天将使用clang编译.c文件,来看看block是怎么实现修改外部变量的

首先,我们看下block声明后是怎样的

main.c

#include 

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 

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 

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的指针地址,所以就达到了修改的目的。

今天先分享到这。
如发现分析得不对、不合理的地方,欢迎提出讨论~

你可能感兴趣的:(iOS底层原理 - block如何修改外部变量)