返回

从零直击iOS底层之block详解

IOS

揭开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的实现函数。