Swift Swift与C语言指针友好合作
2016-06-27 21:52
344 查看
Objective-C和C的API常常会需要用到指针。Swift中的数据类型都原生支持基于指针的Cocoa API,不仅如此,Swift会自动处理部分最常用的将指针作为参数传递的情况。这篇文章中,我们将着眼于在Swift中让C语言指针与变量、数组和字符串共同工作。
C和Objective-C并不支持多返回值,所以Cocoa API中常常将指针作为一种在方法间传递额外数据的方式。Swift允许指针被当作
另一种常见的情况是Cocoa中
为了安全性,Swift要求被使用
在C语言中,数组和指针的联系十分紧密,而Swift允许数组能够作为指针使用,从而与基于数组的C语言API协同工作更加简单。一个固定的数组可以使用一个常量指针直接传递,一个变化的数组可以用
C语言中用
Swift很努力地使与C语言指针的交互更加便利,因为它们广泛地存在于Cocoa之中,同时保持一定的安全性。然而,相比你的其他Swift代码与C语言的指针交互具有潜在的不安全性,所以务必要小心使用。其中特别要注意:
如果被调用者为了在其返回值之后再次使用而保存了C指针的数据,那么这些转换使用起来并不安全。转换后的指针仅在调用期间保证有效。甚至你将同样的变量、数组或字符串作为多指针参数再次传递,你每次都会收到一个不同的指针。这个异常将全局或静态地储存为变量。你可以安全地将这段地址当作永久唯一的指针使用。例如:作为一个KVO上下文参数使用的时候。
当指针类型为
如果你需要使用基于指针的API时没有遵守以上指导,或是你重写了接受指针参数的Cocoa方法,于是你可以在Swift中直接用不安全的指针来使用未经处理的内存。在未来的文章中我们将着眼于更加高级的情况。
用以输入/输出的参数指针
C和Objective-C并不支持多返回值,所以Cocoa API中常常将指针作为一种在方法间传递额外数据的方式。Swift允许指针被当作inout参数使用,所以你可以用符号
&将对一个变量的引用作为指针参数传递。举例来说:
UIColor中的
getRed(_:green:blue:alpha:)方法需要四个
CGFloat*指针来接收颜色的组成信息,我们使用
&来将这些组成信息捕获为本地变量:
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 color.getRed(&r, green: &g, blue: &b, alpha: &a)
另一种常见的情况是Cocoa中
NSError的习惯用法。许多方法会使用一个
NSError**参数来储存可能的错误的信息。举例来说:我们用
NSFileManager的
contentOfDirectoryAtPath(_:error:)方法来将目录下的内容列表,并将潜在的错误指向一个
NSError?变量:
var maybeError: NSError? if let contents = NSFileManager.defaultManager() .contentsOfDirectoryAtPath("/usr/bin", error: &maybeError) { // Work with the directory contents } else if let error = maybeError { // Handle the error }
为了安全性,Swift要求被使用
&传递的变量已经初始化。因为无法确定这个方法会不会在写入数据前尝试从指针中读取数据。
作为数组使用的参数指针
在C语言中,数组和指针的联系十分紧密,而Swift允许数组能够作为指针使用,从而与基于数组的C语言API协同工作更加简单。一个固定的数组可以使用一个常量指针直接传递,一个变化的数组可以用&运算符将一个非常量指针传递。就和输入/输出参数指针一样。举例来说:我们可以用Accelerate框架中的
vDSP_vadd方法让两个数组
a和
b相加,并将结果写入第三个数组
result。
import Accelerate let a: [Float] = [1, 2, 3, 4] let b: [Float] = [0.5, 0.25, 0.125, 0.0625] var result: [Float] = [0, 0, 0, 0] vDSP_vadd(a, 1, b, 1, &result, 1, 4) // result now contains [1.5, 2.25, 3.125, 4.0625]
用作字符串参数的指针
C语言中用cont char*指针来作为传递字符串的基本方式。Swift中的
String可以被当作一个无限长度UTF-8编码的
const char*指针来传递给方法。举例来说:我们可以直接传递一个字符串给一个标准C和POSIX库方法
puts("Hello from libc") let fd = open("/tmp/scratch.txt", O_WRONLY|O_CREAT, 0o666) if fd < 0 { perror("could not open /tmp/scratch.txt") } else { let text = "Hello World" write(fd, text, strlen(text)) close(fd) }
指针参数转换的安全性
Swift很努力地使与C语言指针的交互更加便利,因为它们广泛地存在于Cocoa之中,同时保持一定的安全性。然而,相比你的其他Swift代码与C语言的指针交互具有潜在的不安全性,所以务必要小心使用。其中特别要注意:如果被调用者为了在其返回值之后再次使用而保存了C指针的数据,那么这些转换使用起来并不安全。转换后的指针仅在调用期间保证有效。甚至你将同样的变量、数组或字符串作为多指针参数再次传递,你每次都会收到一个不同的指针。这个异常将全局或静态地储存为变量。你可以安全地将这段地址当作永久唯一的指针使用。例如:作为一个KVO上下文参数使用的时候。
当指针类型为
Array或
String时,溢出检查不是强制进行的。 基于C语言的API无法增加数组和字符串大小,所以在你将其传递到基于C语言的API之前,你必须确保数组或字符的大小正确。
如果你需要使用基于指针的API时没有遵守以上指导,或是你重写了接受指针参数的Cocoa方法,于是你可以在Swift中直接用不安全的指针来使用未经处理的内存。在未来的文章中我们将着眼于更加高级的情况。
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- Apple Swift学习教程
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 介绍 Fedora 上的 Swift
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用开发中AFNetworking库的常用HTTP操作方法小结
- iOS应用中UISearchDisplayController搜索效果的用法
- iOS App开发中的UISegmentedControl分段组件用法总结
- IOS开发环境windows化攻略
- iOS应用中UITableView左滑自定义选项及批量删除的实现
- iOS中UIAlertView警告框组件的使用教程
- 浅析iOS应用开发中线程间的通信与线程安全问题