美文网首页
OC源码分析-block (一)

OC源码分析-block (一)

作者: TianTianBaby223 | 来源:发表于2019-01-07 22:57 被阅读16次

    一 : 基本结构

    写一个简单的block

    int age = 20;
            
            void (^block)(int, int) =  ^(int a , int b){
                NSLog(@"this is a block! -- %d", age);
                NSLog(@"this is a block!");
                NSLog(@"this is a block!");
                NSLog(@"this is a block!");
            };
    

    block本质其实是一个OC对象,其源码结构如下,
    有一个isa指针,可以看出来block是一OC对象,其中
    main_block_desc这个结构体是对block的描述,reserved是扩展保留,Block_size 是block所占用的大小

    
    struct __block_impl {
      void *isa;
      int Flags;
      int Reserved;
      void *FuncPtr;
    };
    
    struct __main_block_desc_0 {
        size_t reserved;
        size_t Block_size;
    };
    
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      int age;
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int flags=0) : age(_age) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    其中block的impl结构体的结构体保存了block的函数地址

    二 : block执行过程源码分析

    int main(int argc, const char * argv[]) {
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
            // 第一步 : 定义block变量
            void (*block)(void) = &__main_block_impl_0(
                                                       __main_block_func_0,
                                                       &__main_block_desc_0_DATA
                                                       );
    
            //第二步 执行block内部的代码
            block->FuncPtr(block);
        }
        return 0;
    }
    
    

    第一步 : 就是block的一个初始化,使用c++语法,来进行构造函数初始化.最终就是block指向了一个结构体对象,两个参数分别是,函数的地址,和block的信息
    第一个参数函数地址最终保存在,block所指向结构体的impl->FuncPtr中.
    第二个参数desc保存在block所指向Desc

    构造函数初始化

    第二步取出block所指向结构体中的impl中的FuncPtr 函数地址,调用函数.

    三 : 变量捕获

    • auto捕获
    变量捕获
             auto:自动变量,离开作用域就销毁
            auto int age = 10;
          void (^block)(void) = ^{
                // age的值捕获进来(capture)
               NSLog(@"age is %d,", age);      
     };
    
    图示

    age值传递到结构体变量中

    • static

    static 修饰的变量,代码块过掉后不会销毁.

     auto:自动变量,离开作用域就销毁
          auto int age = 10;
           static int height = 10;
    
            void (^block)(void) = ^{
               // age的值捕获进来(capture)
               NSLog(@"age is %d, height is %d", age, height);
            };
    
    图例

    height地址传递
    在block结构中height指针接受传过来的&height地址

    执行的时候取出height指针所指向的值


    • 全局变量

    全局变量

    直接访问全局变量,不会捕获到block内部.

    四 : block类型

    block类型

    相关文章

      网友评论

          本文标题:OC源码分析-block (一)

          本文链接:https://www.haomeiwen.com/subject/bgeerqtx.html