swift与oc的互用--c语言API交互

转自译者:shockinglee(git主页

作为与Objective-C语言的互操作性的一部分,Swift也保持了一些与C语言的类型和功能的兼容性,如果你的代码有需要,Swift还提供了使用常见的C结构和模式的方式,如果你的代码需要的话。


基本数据类型

Swift提供了一些等同于C语言基本类型,如char、int、float和double等。然而,这些类型和Swift核心基本类型之间没有隐式转换,如Int。因此,只有你的代码明确要求它们时再使用这些类型,而Int可以在任何你想使用它的时候使用。

 

枚举

Swift引进了Swift枚举标作为任何用宏NS_ENUM来标记的C风格的枚举。这意味着无论枚举值是在系统框架还是在自定义的代码中定义的,当他们导入到Swift时,他们的前缀名称将被截断。例如,看这个Objective-C枚举:

 
 
  1. //Objective-C 
  2. typedef NS_ENUM(NSInteger, UITableViewCellStyle) { 
  3.     UITableViewCellStyleDefault, 
  4.     UITableViewCellStyleValue1, 
  5.     UITableViewCellStyleValue2, 
  6.     UITableViewCellStyleSubtitle 
  7. }; 

 

在Swift中这样来使用:

 
 
  1. //Swift 
  2. enum UITableViewCellStyle: Int { 
  3.     case Default 
  4.     case Value1 
  5.     case Value2 
  6.     case Subtitle 

 

当您需要指向一个枚举值时,使用以点(.)开头的枚举名称:

 
 
  1. //Swift 
  2. let cellStyle: UITableViewCellStyle = .Default 

Swift也引进了标有NS_OPTIONS宏选项。而选项的行为类似于引进的枚举,选项还可以支持一些位操作,如&,|以及?。在Objective-C中,你用一个空的选项设置标示恒为零(0)。在Swift中,使用nil代表没有任何选项。

 

指针

只要可能,Swift尽可能避免让您直接访问指针。然而,当您需要直接操作内存的时候,Swift也为您提供了多种指针类型。下面的表使用Type作为占位符类型名称来表示语法的映射。

 对于参数,以下映射适用:

对于返回类型,变量和参数类型的多层次指针,以下映射应用:

对于类(class)类型,以下映射适用:

C 可变指针

当一个函数被声明为接受CMutablePointer<Type>参数时,这个函数可以接受下列任何一个类型作为参数:


1.nil,作为空指针传入。

2.一个CMutablePointer<Type>值。

3.一个操作数是Type类型的左值的 in-out 表达式,作为这个左值的内存地址传入。

4.一个in-out Type[]值,作为一个数组的起始指针传入,并且它的生命周期将在这个调用期间被延长。

 

如果您像这样声明了一个函数:

 
 
  1. //Swift 
  2. func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ } 

 

那么您可以使用以下任何一种方式来调用这个函数:

 
 
  1. //Swift 
  2. var x: Float = 0.0 
  3. var p: CMutablePointer<Float> = nil 
  4. var a: Float[] = [1.0, 2.0, 3.0] 
  5.  
  6. takesAMutablePointer(nil) 
  7. takesAMutablePointer(p) 
  8. takesAMutablePointer(&x) 
  9. takesAMutablePointer(&a) 

当函数被声明使用一个CMutableVoidPointer参数,那么这个函数接受任何和CMutablePointer<Type>类型相似的Type操作数。

 

如果您这样定义了一个函数:

 
 
  1. //Swift 
  2. func takesAMutableVoidPointer(x: CMutableVoidPointer) { /* ... */ } 

 

那么您可以使用以下任何一种方式来调用这个函数:  

 
 
  1. //Swift 
  2. var x: Float = 0.0, y: Int = 0 
  3. var p: CMutablePointer<Float> = nil, q: CMutablePointer<Int> = nil 
  4. var a: Float[] = [1.0, 2.0, 3.0], b: Int = [1, 2, 3] 
  5.  
  6. takesAMutableVoidPointer(nil) 
  7. takesAMutableVoidPointer(p) 
  8. takesAMutableVoidPointer(q) 
  9. takesAMutableVoidPointer(&x) 
  10. takesAMutableVoidPointer(&y) 
  11. takesAMutableVoidPointer(&a) 
  12. takesAMutableVoidPointer(&b) 

 

C 常指针

当一个函数被声明为接受CConstPointer<Type>参数时,这个函数可以接受下列任何一个类型作为参数:

1.nil,作为空指针传入。

2.一个CMutablePointer<Type>, CMutableVoidPointer, CConstPointer<Type>, CConstVoidPointer, 或者在必要情况下转换成CConstPointer<Type>的AutoreleasingUnsafePointer<Type>值。

3.一个操作数是Type类型的左值的in-out表达式,作为这个左值的内存地址传入。

4.一个Type[]数组值,作为一个数组的起始指针传入,并且它的生命周期将在这个调用期间被延长。

 

如果您这样定义了一个函数:

 
 
  1. //Swift 
  2. func takesAConstPointer(x: CConstPointer<Float>) { /*...*/ } 

 

那么您可以使用以下任何一种方式来调用这个函数:

 
 
  1. //Swift 
  2. var x: Float = 0.0 
  3. var p: CConstPointer<Float> = nil 
  4.  
  5. takesAConstPointer(nil) 
  6. takesAConstPointer(p) 
  7. takesAConstPointer(&x) 
  8. takesAConstPointer([1.0, 2.0, 3.0]) 

当函数被声明使用一个CConstVoidPointer参数,那么这个函数接受任何和CConstPointer<Type>相似类型的Type操作数。 ? 

 

如果您这样定义了一个函数:

 
 
  1. //Swift 
  2. ????func takesAConstVoidPointer(x: CConstVoidPointer) { /* ... */ } 

 

那么您可以使用以下任何一种方式来调用这个函数: ?

 
 
  1. //Swift 
  2. var x: Float = 0.0, y: Int = 0 
  3. var p: CConstPointer<Float> = nil, q: CConstPointer<Int> = nil takesAConstVoidPointer(nil) 
  4. takesAConstVoidPointer(p) 
  5. takesAConstVoidPointer(q) 
  6. takesAConstVoidPointer(&x) 
  7. takesAConstVoidPointer(&y) 
  8. takesAConstVoidPointer([1.0, 2.0, 3.0]) takesAConstVoidPointer([1, 2, 3]) 

 

自动释放不安全指针

当一个函数被声明接受AutoreleasingUnsafePointer<Type>参数时,这个函数可以接受下列任何一个类型作为参数:

1.nil,作为空指针传入。

2.一个AutoreleasingUnsafePointer<Type>值。

3.其操作数是原始的,复制到一个临时的没有所有者的缓冲区的一个输入输出表达式,该缓冲区的地址传递给调用,并返回时,缓冲区中的值加载,保存,并重新分配到操作数。

 

注:这个列表没有包含数组。

 

如果您这样定义了一个函数:

 
 
  1. //Swift 
  2. func takesAnAutoreleasingPointer(x: AutoreleasingUnsafePointer<NSDate?>) { /* ... */ } 

 

那么您可以使用以下任何一种方式来调用这个函数:

 
 
  1. //Swift 
  2. var x: NSDate? = nil 
  3. var p: AutoreleasingUnsafePointer<NSDate?> = nil 
  4. takesAnAutoreleasingPointer(nil) 
  5. takesAnAutoreleasingPointer(p) 
  6. takesAnAutoreleasingPointer(&x) 

注:C语言函数指针没有被Swift引进。

 

全局常量

在C和Objective-C语言源文件中定义的全局常量会自动地被Swift编译引进并做为Swift的全局常量。

 


预处理指令

Swift编译器不包含预处理器。取而代之的是,它充分利用了编译时属性,生成配置和语言特性来完成相同的功能。因此,Swift没有引进预处理指令。

 

简单宏

在C和Objective-C,您通常使用的#define指令定义的一个基本常数,在Swift,您可以使用全局常量来代替。例如:一个全局定义#define FADE_ANIMATION_DURATION 0.35,在Swift可以使用let FADE_ANIMATION_DURATION = 0.35来更好的表述。由于简单的用于定义常量的宏会被直接被映射成Swift全局量,Swift编译器会自动引进在C或Objective-C源文件中定义的简单宏。

 

复杂宏

在C和Objective-C中使用的复杂宏在Swift中并没有副本。复杂宏是那些不用来定义常量的宏,包含带括号的函数式宏。您在C和Objective-C使用复杂的宏以避免类型检查的限制,或避免重新键入大量的样板代码。然而,宏也会产生Bug和重构的困难。在Swift中你可以使用函数和泛型来达到同样的效果,无需任何的妥协。因此,在C和Objective-C源文件中定义的复杂宏在Swift是不能使用的。

 

编译配置

Swift代码和C、Objective-C代码被有条件地,以不同方式编辑。SWIFT代码可以根据生成配置的评价可以有条件地编译。生成配置包括true和false字面值、命令行标志以及下表中的平台测试函数。您可以使用-D <#Flag#>指定命令行标志。

注意:arch(arm) 的编译配置不会为64位arm设备返回true。当为32位iOS 模拟器编译代码时,arch(i386)的编译配置返回true。

 

一个简单的有条件编译可以像下面这段代码:

 
 
  1. #if build configuration 
  2.   statements 
  3. #else 
  4.   statements 
  5. #endif 

 

一个由零个或多个有效的Swift语句声明的statements,可以包括表达式,语句和控制流语句。您可以添加额外的构建配置要求,条件编译说明用&&和| |操作符,否定生成配置使用!操作符,添加条件控制块用#elseif:

 
 
  1. #if build configuration && !build configuration 
  2.   statements 
  3. #elseif build configuration 
  4.   statements 
  5. #else 
  6.   statements 
  7. #endif 

与C语言编译器的条件编译相反,Swift条件编译语句必须完全是自包含和语法有效的代码块。这是因为即使它没有被编译的Swift代码也是被进行语法检查。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值