从零直击iOS底层之block详解
2023-10-13 07:31:12
揭开block的神秘面纱
在iOS开发中,block作为一种强大的匿名函数,经常被用来实现各种复杂的逻辑处理。然而,大多数开发者对block的底层原理却知之甚少。本文将带你一起深入探索block的内部机制,揭开它的神秘面纱。
block的结构体
通过查看block的源码,我们可以发现block本质上是一个结构体,名为__block_impl。该结构体包含了许多成员变量,其中最重要的两个是isa指针和function pointer。isa指针指向block的真实类型,而function pointer则指向block的实现函数。
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
block的构造函数
当我们创建一个block时,系统会自动调用block的构造函数来初始化block的成员变量。block的构造函数位于__main_block_impl_0函数中。在这个函数中,系统首先会将isa指针指向_NSConcreteStackBlock类型的地址,然后将function pointer指向block的实现函数。
__attribute__((noinline)) static id __main_block_impl_0(void *fp, const char *name, const char *signature, const char *generic) {
__block_impl *result = (__block_impl *)__builtin_alloca(sizeof(struct __block_impl));
result->isa = &_NSConcreteStackBlock;
result->Flags = 0;
result->Reserved = 0;
result->FuncPtr = fp;
return result;
}
block的isa指针
isa指针是block结构体中最重要的成员变量之一。它指向block的真实类型。在iOS中,block的真实类型可以是_NSConcreteStackBlock或_NSConcreteGlobalBlock。
- _NSConcreteStackBlock: 栈block。当block在栈上分配内存时,它的真实类型为_NSConcreteStackBlock。栈block的特点是生命周期与函数调用栈相关,当函数调用栈销毁时,栈block也会随之销毁。
- _NSConcreteGlobalBlock: 堆block。当block在堆上分配内存时,它的真实类型为_NSConcreteGlobalBlock。堆block的特点是生命周期与对象的生命周期相关,当对象销毁时,堆block也会随之销毁。
block的存储方式
block可以在栈上或堆上分配内存。当block在栈上分配内存时,它被称为栈block。当block在堆上分配内存时,它被称为堆block。
- 栈block: 栈block的存储方式与普通函数类似,它直接存储在函数调用栈中。栈block的特点是生命周期与函数调用栈相关,当函数调用栈销毁时,栈block也会随之销毁。
- 堆block: 堆block的存储方式与普通对象类似,它存储在堆内存中。堆block的特点是生命周期与对象的生命周期相关,当对象销毁时,堆block也会随之销毁。
block的执行机制
当block被调用时,系统会首先检查block的isa指针,然后根据block的isa指针来确定block的真实类型。如果block的真实类型是_NSConcreteStackBlock,则系统会直接调用block的实现函数。如果block的真实类型是_NSConcreteGlobalBlock,则系统会先将block的实现函数拷贝到栈上,然后再调用block的实现函数。
结语
通过本文的学习,我们对block的底层原理有了更深入的理解。我们了解到block本质上是一个结构体,名为__block_impl。我们还了解到block的构造函数位于__main_block_impl_0函数中,在这个函数中,系统会将isa指针指向block的真实类型,然后将function pointer指向block的实现函数。我们还了解到block的isa指针指向block的真实类型,block的存储方式可以是栈上或堆上,block的执行机制根据block的isa指针来确定block的真实类型,然后根据block的真实类型来调用block的实现函数。