搜索
您的当前位置:首页正文

OC源码分析-block (一)

来源:二三娱乐

一 : 基本结构

写一个简单的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类型
Top