返回

剖析 iOS 面试题中的重点难点——Block

IOS

Block 的内部实现

Block 是 Objective-C 中的闭包,它允许您将代码块作为参数传递给其他函数。Block 的内部实现基于结构体,它包含指向函数的指针、函数的参数和局部变量。当 Block 被调用时,它会创建一个新的栈帧,并将局部变量压入栈中。然后,它会调用指向函数的指针,并传递参数。函数执行完成后,栈帧被弹出,Block 被销毁。

Block 的结构

Block 的结构如下:

struct Block {
    void *isa;
    int flags;
    int reserved;
    void (*invoke)(void *, ...);
    struct BlockDescriptor *descriptor;
};
  • isa:指向 Block 的类对象的指针。
  • flags:包含 Block 的标志位,例如是否可以捕获外部变量。
  • reserved:保留字段,未被使用。
  • invoke:指向 Block 函数的指针。
  • descriptor:指向 Block 符的指针。

Block 是否属于类

Block 不是类,它是一种数据结构。Block 虽然具有函数的某些特性,但它不是类实例,也不支持面向对象编程的特性,例如继承和多态性。

Block 的类型

Block 有两种类型:

  • 堆 Block :在堆上分配内存的 Block。堆 Block 可以捕获外部变量,并且可以在 Block 之间传递。
  • 栈 Block :在栈上分配内存的 Block。栈 Block 不能捕获外部变量,只能在函数内部使用。

一个 int 变量被 __block 修饰与否的区别

当一个 int 变量被 __block 修饰时,它表示该变量可以被 Block 捕获。这意味着 Block 可以修改该变量的值,即使 Block 在函数之外被调用。如果一个 int 变量没有被 __block 修饰,则它不能被 Block 捕获,Block 只能访问该变量的副本。

以下示例演示了 __block 修饰符的使用:

void testBlock() {
    int value = 10;

    // 创建一个 Block 并捕获变量 value
    void (^block)(void) = ^{
        value++;
    };

    // 调用 Block
    block();

    // 打印 value 的值
    printf("Value: %d\n", value);
}

在上面的示例中,变量 value 被 __block 修饰,因此它可以被 Block 捕获。当 Block 被调用时,它会修改变量 value 的值。因此,当打印 value 的值时,输出结果为 11。

如果您想了解更多关于 Block 的信息,可以参考 Apple 的官方文档:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html