標籤:des style blog http io color ar os 使用
Swift與C指標互動
Objective-C和C API經常須要使用指標. 在設計上, Swift資料類型能夠自然的與基於指標的Cocoa API一起工作, Swift自己主動處理幾種經常使用的指標參數. 在本文中, 我們將看到C中的指標參數怎樣與Swift中的變數,數組,字串一起工作.
指標作為輸入/輸出參數
C和Objective-C不支援多個返回值, 所以Cocoa API常常使用指標傳遞附加參數到函數. Swift同意把指標參數看成[inout]參數, 所以你能夠用相同的&文法傳遞一個變數的引用作為指標. 比如: UIColor的getRed(_:green:blue:alpha:)方法使用4個CGFloat*指標來接受顏色的組合. 我們能夠用&來得到這些值:
var r: CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0color.getRed(&r, green: &g, blue: &b, alpha: &a)
還有一個常常使用的是NSError. 很多方法使用了NSError*參數來儲存發生的錯誤. 比如: 我們列舉檔案夾裡的內容使用NSFileManager的contentsOfDirectoryAtPath(_:error:)方法, 直接使用NSError?變數來儲存可能的錯誤:
var maybeError:NSError? if let contents = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/usr/bin", error: &maybeError){ //內容處理 for i in contents{ println(i) } }else if let error = maybeError{ //錯誤處理 println(error.description) }
安全起見, Swift要求變數在使用&前須要初始化. 由於它不知道被調用的方法是否在改動它之前會讀取指標
數組指標
在C中數組與指標緊緊相連. 為方便使用基於數組的C API, Swift同意將Array作為指標. 不可改動數組能夠直接當成常量指標, 可改動數組能夠使用&操作符做為很量指標(就和inout參數一樣). 比如: 我們把兩個數組 a 和 b 使用vDSP_vadd函數(Accelerte framework)相加, 把結果寫到第三個數組 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使用 const char*指標作為傳遞字串的主要方式. Swift String能夠作為const char*指標, 它會給函數傳遞一個 null結束, UTF-8編碼的字串指標. 比如, 我們能夠直接給標準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指標的互動方便並提供了一定的安全性, 由於C指標無處不在. 可是, 與C指標互動相對於Swift代碼來說還是記憶體的不安全, 因此須要特別注意. 特別的:
* These conversions cannot safely be used if the callee saves the pointer value for use after it returns. The pointer that results from these conversions is only guaranteed to be valid for the duration of a call. Even if you pass the same variable, array, or string as multiple pointer arguments, you could receive a different pointer each time. An exception to this is global or static stored variables. You can safely use the address of a global variable as a persistent unique pointer value, e.g.: as a KVO context parameter.
* Array和String指標沒有邊界檢查. C API不會擴大數組和字串, 因此在調用前你須要為它分配足夠的大小
假設上面的指南不滿足你指標互動的須要, 或者你想手動控制指標參數, 你能夠直接使用unsafe指標操作記憶體. 我們會在將來的文章中看到很多其它進階應用程式.
iOS: 學習筆記, Swift與C指標互動(譯)