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);
}
关键机制:
-
变量捕获:
- 基本类型:值捕获
- 对象类型:强引用捕获
-
__block
变量:包装为__Block_byref
结构体
-
内存管理:
objectivec
// 栈Block -> 堆Block转换 void (^heapBlock)(void) = [^{} copy]; [heapBlock release];
-
循环引用解决方案:
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
关键机制:
-
变量捕获:
swift
var a = 10 let closure = { a += 1 // a被捕获到Box中 print(a) }
-
捕获列表:
swift
[unowned self, b = a + 1] in // 显式控制捕获
-
内存管理:
- 非逃逸闭包:栈分配
- 逃逸闭包:堆分配(自动引用计数)
-
循环引用解决方案:
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不捕获变量 | 非逃逸闭包可栈分配 |
调用开销 | 通过函数指针调用 | 通过上下文+函数指针调用 |
性能关键点:
-
Objective-C:
objectivec
// 优先使用栈Block void (^stackBlock)(void) = ^{ /* ... */ }; // 需要长期持有时才复制到堆 void (^heapBlock)(void) = [stackBlock copy];
-
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);
通过深入分析底层实现,可以更好地理解闭包的内存行为、性能特征和最佳实践,避免常见陷阱如循环引用和性能损耗。