Swift 类型映射到 Objective-C 的过程是由 Swift 编译器(Clang 与 Swift 编译器前端)通过生成的 -Swift.h 桥接头文件 自动完成的。
由于 Swift 是静态强类型且支持值类型,而 Objective-C 几乎一切皆对象,这种映射本质上是**“类型降级”和“引用封装”**的过程。
1. 基础数据类型的映射
Swift 的基础类型通过 Swift 标准库与 Foundation 框架的深度集成,实现了自动桥接。
| Swift 类型 | Objective-C 类型 | 映射机制 |
|---|---|---|
Int, Float, Double, Bool | NSInteger, float, double, BOOL | 直接映射为 C 标量类型。 |
String | NSString * _Nonnull | 自动桥接,处理值拷贝与引用。 |
Array<Element> | NSArray<Element> * | 泛型会尽可能保留(如果 Element 兼容 OC)。 |
Dictionary<Key, Value> | NSDictionary<Key, Value> * | 同上。 |
Optional<T> | T _Nullable 或 T _Nonnull | 映射为指针的 nil 可靠性。 |
2. 引用类型 (Class)
Swift 的类要映射到 OC,必须满足两个条件:继承自 NSObject 且标记为 @objc。
- 成员变量与属性:Swift 属性会映射为 OC 的
@property。Swift 的let属性在 OC 中表现为readonly。 - 初始化器:Swift 的
init会映射为 OC 的initWith...风格的方法。 - 方法名转换:Swift 的参数标签会转化为 OC 的方法签名,例如
func move(to point: CGPoint)映射为- (void)moveToPoint:(CGPoint)point。
3. 值类型 (Struct & Enum)
这是映射中最受限的部分,因为 OC 不支持 Swift 的现代值类型特征。
结构体 (Struct)
- 原生 Struct 无法直接映射:OC 无法识别 Swift 的
struct。 - 对策:必须将 Struct 包装在
NSObject的类中,或者使用符合 OC 规范的C Struct(但这将失去 Swift 结构体的方法特性)。
枚举 (Enum)
- 简单枚举:只要指定为
Int原始值(Raw Value)并标记为@objc,可以映射为NS_ENUM。 - 带关联值的枚举 (Associated Values) :无法映射。OC 的枚举只是简单的整数,无法承载 Swift 枚举复杂的内存布局(Tagged Unions)。
4. 特殊类型的特殊处理
闭包 (Closures) vs 块 (Blocks)
Swift 的闭包会自动映射为 OC 的 Block。
- Swift:
(Int) -> String - OC:
NSString * (^)(NSInteger)
注意:映射过程中,编译器会自动处理逃逸(Escaping)语义和内存管理。
协议 (Protocol)
如前所述,只有标记为 @objc 的协议才能映射。OC 无法理解 Swift 协议的关联类型(associatedtype)和泛型约束。
指针 (Pointers)
Swift 的安全指针与非安全指针会映射为相应的 C 指针类型:
UnsafePointer<T>映射为const T *。UnsafeMutableRawPointer映射为void *。
5. 映射中的“修饰符”转换
编译器会根据 Swift 的修饰符在 -Swift.h 中添加对应的宏:
weak:映射为__weak。unowned:映射为__unsafe_unretained(OC 中没有完全等价的非拥有引用)。throwing:映射为带NSError **参数的方法,并返回BOOL或可选值。
💡 避坑指南:映射失效
如果你的 Swift 类中包含 元组 (Tuples) 、泛型结构体 或 嵌套类型,这些成员在生成的 .h 文件中会直接消失,因为 Objective-C 没有任何语法能表达它们。