普通视图

发现新文章,点击刷新页面。
昨天以前首页

Objective-C 和 Swift 闭包内部实现详解

2025年6月30日 09:45

底层结构

c

// Block 基础结构体
struct Block_layout {
    void *isa;              // 指向类信息:_NSConcreteGlobalBlock/_NSConcreteStackBlock/_NSConcreteMallocBlock
    int flags;              // 状态标志位
    int reserved;           // 保留字段
    void (*invoke)(void *, ...); // 函数指针
    struct Block_descriptor *descriptor; // 描述信息
    // 捕获的变量跟随在此后
};

// Block 描述符
struct Block_descriptor {
    unsigned long reserved;
    unsigned long size;     // Block 总大小
    void (*copy)(void *dst, const void *src);     // 拷贝辅助函数
    void (*dispose)(const void *); // 析构辅助函数
};

// __block 变量包装结构
struct __Block_byref {
    void *isa;
    struct __Block_byref *forwarding;  // 指向真实地址
    int flags;
    int size;
    // 原始变量存储在此
};

完整实现示例

objectivec

// 原始代码
void example() {
    __block int counter = 0;
    void (^block)(void) = ^{ counter++; };
}

// 编译器转换后的伪代码
struct __block_impl_counter {
    void *isa = &_NSConcreteStackBlock;
    int flags = 0;
    int reserved;
    void (*invoke)(struct __block_impl *);
    struct __Block_descriptor *descriptor;
    struct __Block_byref_counter *counter_ref; // 捕获的__block变量
};

struct __Block_byref_counter {
    void *isa;
    __Block_byref_counter *forwarding;
    int flags;
    int size;
    int counter;  // 原始变量
};

static void __example_block_invoke(struct __block_impl *__cself) {
    struct __Block_byref_counter *counter_ref = __cself->counter_ref;
    counter_ref->forwarding->counter++; // 通过forwarding指针修改
}

static void __example_block_copy(struct __block_impl *dst, struct __block_impl *src) {
    _Block_object_assign(&dst->counter_ref, src->counter_ref, BLOCK_FIELD_IS_BYREF);
}

static void __example_block_dispose(struct __block_impl *src) {
    _Block_object_dispose(src->counter_ref, BLOCK_FIELD_IS_BYREF);
}

static struct __Block_descriptor {
    unsigned long reserved;
    unsigned long size;
    void (*copy)(struct __block_impl *, struct __block_impl *);
    void (*dispose)(struct __block_impl *);
} __block_descriptor = { 0, sizeof(struct __block_impl), __example_block_copy, __example_block_dispose };

void example() {
    // 创建__block变量
    struct __Block_byref_counter counter_ref = {
        NULL,
        &counter_ref,  // forwarding指向自己
        0,
        sizeof(struct __Block_byref_counter),
        0 // counter初始值
    };
    
    // 创建Block
    struct __block_impl block_impl = {
        &_NSConcreteStackBlock,
        BLOCK_HAS_COPY_DISPOSE,
        0,
        __example_block_invoke,
        &__block_descriptor
    };
    block_impl.counter_ref = &counter_ref;
    
    // 当Block被复制到堆时
    struct __block_impl *heap_block = malloc(sizeof(struct __block_impl));
    memcpy(heap_block, &block_impl, sizeof(struct __block_impl));
    __example_block_copy(heap_block, &block_impl);  // 处理捕获变量
    
    // 堆上Block的isa指针更新
    heap_block->isa = &_NSConcreteMallocBlock;
    
    // __block变量复制到堆
    struct __Block_byref_counter *heap_counter = malloc(sizeof(struct __Block_byref_counter));
    memcpy(heap_counter, &counter_ref, sizeof(struct __Block_byref_counter));
    heap_counter->forwarding = heap_counter;  // 指向堆上副本
    counter_ref.forwarding = heap_counter;    // 栈变量指向堆副本
    
    // 调用Block
    heap_block->invoke(heap_block);
}

关键机制:

  1. 变量捕获

    • 基本类型:值捕获
    • 对象类型:强引用捕获
    • __block变量:包装为__Block_byref结构体
  2. 内存管理

    objectivec

    // 栈Block -> 堆Block转换
    void (^heapBlock)(void) = [^{} copy];
    [heapBlock release];
    
  3. 循环引用解决方案

    objectivec

    __weak typeof(self) weakSelf = self;
    self.block = ^{ 
        __strong typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf doSomething];
    };
    

Swift Closure 内部实现原理及代码

底层结构

c

// Swift闭包在SIL(Swift中间语言)中的表示
struct Closure {
    void *metadata;                     // 类型元数据
    struct HeapObject *object;          // 引用计数头部
    void (*function)(void *context);    // 函数指针
    struct Context *context;            // 捕获上下文
};

// 捕获上下文结构
struct Context {
    void *metadata;
    struct HeapObject *object;
    // 捕获的变量按顺序排列
    // 对于值类型:直接存储值
    // 对于引用类型:存储指针
};

完整实现示例

swift

// 原始Swift代码
func createClosure() -> () -> Void {
    var counter = 0
    return { counter += 1 }
}

// 编译器生成的伪代码
struct Context {
    // 引用计数头
    struct HeapObject {
        void *metadata;
        atomic_int refCount;
    } header;
    
    // 捕获的变量
    struct Box {
        int value;  // counter的存储
    } *counterBox;
};

// 闭包函数实现
void closureImp(struct Context *context) {
    context->counterBox->value += 1; // 修改捕获变量
}

// 创建闭包
Closure createClosure() {
    // 在堆上分配上下文
    struct Context *context = swift_allocObject(sizeof(struct Context));
    
    // 在堆上分配Box存储counter
    context->counterBox = swift_allocObject(sizeof(struct Box));
    context->counterBox->value = 0;
    
    // 创建闭包实例
    return (Closure){
        .metadata = ClosureTypeMetadata,
        .object = &context->header,
        .function = closureImp,
        .context = context
    };
}

// 调用闭包
let closure = createClosure()
closure.function(closure.context) // counter = 1

关键机制:

  1. 变量捕获

    swift

    var a = 10
    let closure = { 
        a += 1  // a被捕获到Box中
        print(a)
    }
    
  2. 捕获列表

    swift

    [unowned self, b = a + 1] in // 显式控制捕获
    
  3. 内存管理

    • 非逃逸闭包:栈分配
    • 逃逸闭包:堆分配(自动引用计数)
  4. 循环引用解决方案

    swift

    class MyClass {
        var closure: (() -> Void)?
        
        func setup() {
            closure = { [weak self] in
                self?.doSomething()
            }
        }
    }
    

对比总结

特性 Objective-C Block Swift Closure
内存分配 手动管理(栈/堆转换需copy 自动管理(ARC)
值类型捕获 默认值捕获,__block修饰可修改 直接可修改(自动Boxing)
引用类型 强引用捕获 强引用捕获
生命周期控制 __weak/__strong [weak]/[unowned]/捕获列表
逃逸行为 无显式标记 @escaping显式标记
优化 全局Block不捕获变量 非逃逸闭包可栈分配
调用开销 通过函数指针调用 通过上下文+函数指针调用

性能关键点:

  1. Objective-C

    objectivec

    // 优先使用栈Block
    void (^stackBlock)(void) = ^{ /* ... */ };
    
    // 需要长期持有时才复制到堆
    void (^heapBlock)(void) = [stackBlock copy];
    
  2. Swift

    swift

    // 非逃逸闭包优化(编译器自动识别)
    func optimize(@noescape _ closure: () -> Void) {
        closure()
    }
    
    // 避免不必要的捕获
    let safeClosure = { [weak self] in
        guard let self = self else { return }
        self.process()
    }
    

特殊场景处理:

Swift 自动闭包

swift

// @autoclosure 实现
func assert(_ condition: @autoclosure () -> Bool) {
    if !condition() { /* 处理 */ }
}

// 编译器转换:
func assert(_ condition: () -> Bool) {
    if !condition() { /* ... */ }
}
assert({ 2 > 1 }())  // 自动包装

Objective-C Block 与 C 交互

objectivec

// 作为C函数参数
void acceptBlock(void (^block)(void));

// 桥接调用
void (^ocBlock)(void) = ^{ NSLog(@"Called"); };
acceptBlock((__bridge void (^)(void))ocBlock);

通过深入分析底层实现,可以更好地理解闭包的内存行为、性能特征和最佳实践,避免常见陷阱如循环引用和性能损耗。

❌
❌