美文网首页
block本质

block本质

作者: 有毒的程序猿 | 来源:发表于2018-12-24 11:28 被阅读4次
1.C++源码预览
 int a = 10;
 void(^block)(void) = ^{
        NSLog(@"Hello, World! %d",a);
  };
  block();

通过clang -rewrite-objc main.m生成cpp文件

// 代码变为
int a = 10;
void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a));
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

// 一看是不是有点蒙蔽我们去掉强制装换来看一下

int a = 10;
void(*block)(void) = 
&__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a); 
// 这一句就是调用一个c的方法,并取这个方法的地址,赋值给一个block类型的指针

block->FuncPtr(block);

// 拿到这个block一个成员的FuncPtr方法并调用

先看下这个东西__main_block_impl_0

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int a; // 声明一个和外面一样的变量,并且捕获
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
__main_block_impl_0 其实就是block的本质一个结构体,
里面有个同名字的构造方法返回本身(c++语法).

构造方法里
impl.isa = &_NSConcreteStackBlock;   // 确定isa指向
impl.Flags = flags;                  // 标识为0
impl.FuncPtr = fp;                   // 代码块方法
Desc = desc;                         // 描述

构造函数传进来的参数都赋值给了__main_block_impl_0结构体的成员impl, 
impl也是一个结构体

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

看到没有block也持有一个void *isa指针,所以说block是一个oc对象.

之后看下这个东西__main_block_func_0 就是调用构造函数传进去的参数

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int a = __cself->a; // 此参数可以从上面代码看出,是传的block

  NSLog((NSString *)&__NSConstantStringImpl__var_folders_sf_9x41px110wz4nbxh71bwvwzr0000gp_T_main_dd6554_mi_0,a);
}

这里正好是我们的打印代码,block里面的代码都会放在这里面等待调用

所以说block其实是一个结构体,保存一个函数指针,指向我们写的代码块既一个c函数,等待我们调用.

  • block本质也是一个oc对象,内部也有一个isa指针.
  • block是封装了函数调用及函数调用环境的oc对象.
2.捕获变量
image.png
// 大括号外面
int age3 = 10;            // 全局变量
static int age4 = 10;    // 全局变量静态

// 大括号外面
{
auto int age1 = 10;       // oc默认是auto变量
static int age2 = 10;    // 局部静态
}

通过源码看下两者的却别

#import <Foundation/Foundation.h>

int age3 = 30;
static int age4 = 30;

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        auto int age1 = 10;
        static int age2 = 20;
        void(^block)(void) = ^{
            NSLog(@"Hello, World! %d%d%d%d",age1,age2,age3,age4);
        };
        block();
    }
    return 0;
}

c++

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int age1;
  int *age2;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age1, int *_age2, int flags=0) : age1(_age1), age2(_age2) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int age1 = __cself->age1; // bound by copy
int *age2 = __cself->age2; // bound by copy

NSLog((NSString *)&__NSConstantStringImpl__var_folders_sf_9x41px110wz4nbxh71b
wvwzr0000gp_T_main_b2cff9_mi_0,age1,(*age2),age3,age4);
}

从上面源码看出,只捕获了age1和age2,而age3和age4是直接用的
age1是值,age2是指针,所以age1捕获的是值age2捕获的是指针.
3.block类型
block类型.jpg block存储位置.png
auto int age1 = 10;
void(^block)(void) = ^{
     NSLog(@"Hello, World! %d%d%d%d",age1);
};
block();
NSLog(@"%@",[block class]);

[block class] // 可以直接获取block类型,从这一点也说明block是一个oc对象

arc下系统会自动帮你把block从栈上拷贝到堆上
既调用[block copy]

相关文章

  • Block总结

    一、Block的底层结构及本质 (1)block本质: 从代码可以看出,Block的本质就是NSObject. 也...

  • OC底层原理(八):Block

    block是经常使用的一种技术,那么block的本质是什么呢? Block的本质 block本质上也是OC对象,它...

  • 理清 Block 底层结构及其捕获行为

    来自掘金 《理清 Block 底层结构及其捕获行为》 Block 的本质 本质 Block 的本质是一个 Obje...

  • 2019 知识点总结

    1、Block 释放 追问 (1)Block本质? Block本质就是一个OC对象,内部有isa指针。 Block...

  • iOS开发之Block原理探究

    Block概述 Block本质 Block调用 Block分类 Block循环引用 Block原理探究 Block...

  • Block详解-小码哥

    block本质 block的本质是封装了函数调用和函数调用环境的OC对象。 block结构 Block_layou...

  • iOS-底层原理28:block底层原理

    本文主要介绍:1、block的本质2、block捕获变量3、block的类型4、__block原理 本质 通过cl...

  • block系列文章总结

    iOS源码解析:Block的本质<一>iOS源码解析:Block的本质<二>Objective C block背后...

  • Block详解

    block的本质 先看block的简单实现 转为C++代码 查看Block的继承关系 结论: block本质上也是...

  • iOS Block详解

    第一部分:Block本质 Q:什么是Block,Block的本质是什么? block本质上也是一个OC对象,它内部...

网友评论

      本文标题:block本质

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