在之前讲到基础类型桥接Swift的时候,我们提过会用一组有相同命名规则的变量表示某个范围里相关的值。实际上,我们也可能在C里用一个真正的enum
来表达类似的概念:
// In traditional_oc.h
typedef enum {
RED, YELLOW, GREEN
} TrafficLightColor;
对于这个定义,Swift会如何桥接呢?
不如我们所想的enum桥接
你可能想当然的觉得,直接桥接到Swift原生的enum
不就好了。但实际上并不如此,C中的enum
会被打散成一个同名的struct
和由C中所有的enum
成员命名的全局变量,就像这样:
/// struct TrafficLightColor: RawRepresentable, Equatable { }
/// var RED: TrafficLightColor { get }
/// var YELLOW: TrafficLightColor { get }
/// var GREEN: TrafficLightColor { get }
于是,在Swift里,我们要这样使用TrafficLightColor
:
let r = RED
print(r.rawValue) // 0
可以看到,生成的TrafficLightColor
只有一个rawValue
属性,它的值就是C中每一个enum
成员的值。只是,这些全局变量都是只读的,我们不能修改他们。
当然,这和我们想象的一点儿也不一样。要让C中的enum
直接映射到Swift原生的enum
怎么办呢?我们可以借助一个宏。
使用NS_ENUM
在traditional_oc.h中,把之前TrafficLightColor
的声明改成这样:
typedef NS_ENUM(int, TrafficLightColor) {
RED,
YELLOW,
GREEN
};
其中,NS_ENUM
的第一个参数表示每一个enum
case对应的值类型,第二个参数表示要桥接到Swift的类型名。这样,TrafficLightColor
就会桥接成下面这样的Swift原生enum
:
enum TrafficLightColor: CInt {
case RED,
case YELLOW,
case GREEN
}
我们可以用下面的代码观察这个结果:
let r: TrafficLightColor = .RED
print(type(of: r)) // TrafficLightColor
print(r.rawValue) // 0
print(type(of: r.rawValue)) // Int32
注意这次,我们给r
赋值的时候,使用了.RED
。
What's next?
至此,我们就掌握了C中的各种基本类型桥接到Swift的方式。如果你确认没问题,接下来,我们就要进入到C的腹地,了解Swift中的指针类型家族是如何与C的原生指针进行交互的。