美文网首页
487,Block的代码分析原理(面试点:int age = _

487,Block的代码分析原理(面试点:int age = _

作者: 枫叶1234 | 来源:发表于2021-02-24 06:56 被阅读0次

block数据结构

写下如下代码,然后在终端进入.m文件所在目录,执行命令xcrun -sdkiphoneos clang -arch arm64 -rewrite-objc ArcClass.m 我们可以看到在当前目录生成ArcClass.cpp文件

int age = 18;
void (^block)(void) = ^{
NSLog(@"age is %d",age);
 };
block();

我们可以看到上面的代码变成了

int age = 18;
// block定义
void (*block)(void) = ((void (*)())&__ArcClass__TestArc_block_impl_0((void *)__ArcClass__TestArc_block_func_0,&__ArcClass__TestArc_block_desc_0_DATA, age));
// block调用
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

上面代码删除掉一些强制转换的代码简化如下

int age = 18;
// block定义
void (*block)(void) = & __ArcClass__TestArc_block_impl_0(
                        &__ArcClass__TestArc_block_func_0,
& __ArcClass__TestArc_block_desc_0_DATA,
age
);

// block调用
block->FuncPtr(block);

我们可以看到block是指向__ArcClass__TestArc_block_impl_0对象的指针,结构体__ArcClass__TestArc_block_impl_0定义如下:

struct __ArcClass__TestArc_block_impl_0 {
struct __block_impl impl;
struct __ArcClass__TestArc_block_desc_0*Desc;
int age;
__ArcClass__TestArc_block_impl_0(void *fp,struct __ArcClass__TestArc_block_desc_0 *desc,int _age,int flags=0): age(_age) {
impl.isa =&_NSConcreteStackBlock;
impl.Flags= flags;
impl.FuncPtr= fp;
Desc = desc;
  }
};

该结构体把age直接赋值给了_age,执行的是拷贝操作。

  • 结构体中第一个成员变量是struct __block_impl impl;
struct __block_impl {
 void *isa;
int Flags;
int Reserved;
void *FuncPtr;
}

__block_impl 的成员变量isa代表了该block属于啥类型,本例中为_NSConcreteStackBlock,FuncPtr代表block的调用方法,本例中为__ArcClass__TestArc_block_func_0

  • 第二个成员变量是struct __ArcClass__TestArc_block_desc_0* Desc;
static struct __ArcClass__TestArc_block_desc_0 {
size_t reserved;
size_t Block_size;
}__ArcClass__TestArc_block_desc_0_DATA= { 0, sizeof(struct__ArcClass__TestArc_block_impl_0)};

desc描述了__ArcClass__TestArc_block_impl_0的大小

  • 结构体中第三个是成员变量age
    该结构体把age直接赋值给了_age,执行的是拷贝操作。

  • block调用实际上执行的是__ArcClass__TestArc_block_func_0方法
    下面为 block方法代码NSLog(@"age is %d",age);的实现

static void __ArcClass__TestArc_block_func_0(struct __ArcClass__TestArc_block_impl_0 *__cself) {
//这里访问age是bound by copy ,即拷贝。
int age = __cself->age; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_x0_cw796jjd255431nlsdwjt9840000gn_T_ArcClass_6c36ef_mi_0,age);}

从上面的分析可以看到,定义一个block的时候,底层生成了一个代表block的结构体__ArcClass__TestArc_block_impl_0,该结构体有一个__block_impl类型的impl成员变量和代表捕获变量的成员变量。其中impl的isa 代表了block的类型,FuncPtr代表了block的实际调用方法,该方法的参数为__ArcClass__TestArc_block_impl_0。

相关文章

网友评论

      本文标题:487,Block的代码分析原理(面试点:int age = _

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