原文地址:Working with Cocoa Frameworks
作為與OC交互的一部分,Swift提供了簡單和高效的方式與Cocoa框架一起工作。
Swift自動將一些OC類型轉換為Swift類型,以及自動將一些Swift類型轉換為OC類型。能夠在OC與Swift之間相互轉換的類型被簡稱為橋接類型。例如,在Swift中,你可以傳遞一個String類型的數據給一個帶有NSString類型參數的OC方法。另外,為了在Swift中看起來更自然,許多Cocoa框架,包括Foundation,AppKit和UIKit重新定義了他們的API。例如,NSCoder的decodeObjectOfClass(_:forKey:)利用Swift的泛型提供強類型簽名。
Foundation
Foundation框架為應用程序和其他框架提供一些基礎性的功能,包括數據存儲、文本處理、日期和時間、排序和過濾、持久化以及網絡相關功能。
橋接類型
Swift Foundation為如下的OC類型提供了對應的橋接類型:
這些Swift類型與其對應的類型有相同的功能。包含不可變和可變子類型的類族被橋接到同一個類型。Swift代碼利用var和let去控制是否可修改,所以他不需要兩種類。這些對應的類型能夠像具有NS前綴的類一樣被訪問。
任何你可以使用橋接OC類型的地方,你都可以使用Swift類型來代替。這使得在Swift中你能夠利用這些對應類型的功能。基于這個原因,在你的代碼中你永遠不需要使用橋接類型對應的類型。事實上,當Swift導入OC API時,導入器將OC中的這些類型進行了替換。同樣的,當OC導入Switf API的時候,也做了替換。
類型關聯其中最主要的一個好處是使得reason about your code很簡單。獲取更多關于值類型,參考Classes and Structures 和WWDC 2015 session 414 Building Better Apps with Value Types in Swift
如果需要使用橋接Foundation對象,可以使用as轉換符來轉換橋接類型。
Renamed Types
Swift Foundation重命名了類、協議以及一些相關的枚舉和常量。
除以下幾種特例,被導入的Foundation的類和協議去掉了NS前綴:
一些專門設計用來支持或者用于繼承支持OC runtime的類,例如NSObject、NSAutoreleasePool、NSException、NSProxy
平臺相關的類,例如NSBackgroundActivity、NSUserNotification、NSXPCConnection
有等價的Swift類,如橋接類型中描述的類
一些現在沒有等價但是未來會有等價的類的一些類,例如NSAttributedString、NSRegularExpression、NSPredicate
Strings
Swift 橋接String和NSString。能夠用as操作符將String轉換為NSString,同樣可以直接利用雙引號創建一個NSString對象。
Numbers
Swift橋接NSNumber到Swift的算術類型,包括Int、Double、Bool。
可以使用as將Swift的算術類型轉換為NSNumber。因為NSNumber能夠包含多種類型,所以應該使用as?將NSNumber轉換到Swift的類型,否則可能引發崩潰。同樣也可以直接用浮點數、整數、bool值創建NSNumber類型。
Arrays
Array---NSArray。當橋接模板化的NSArray到Array時,轉換會非常順利。但是如果沒有指定類型,那么Array中的類型將是[Any].
Sets
如果沒有模板化,將是Set<AnyHashable>
Dictionaries
如果NSDictionary中沒有模板化,將是[AnyHashable: Any]
Core Foundation
Core Foundation類型被導入為Swift類。當出現內存管理注釋時,Swift自動管理Core Foundation中的對象內存,包括由我們自己實例化的Core Foundation對象。在Swift中,可以自由變換toll-free bridges Foundation和Core Foundation類型。同樣如果你轉換了bridging Foundation type,你也可以橋接一些toll-free bridged Core Foundation類型到Swift。
Remapped Types
當Swift導入Core Foundation類型時,編譯器重新映射了這些類型。由于Swift本身是引用類型,編譯器移除了每種類型結尾的Ref。
CFTypeRef統一映射為AnyObject類型。所以,當你需要使用CFTypeRef時,使用AnyObject。
Memory Managed Objects
在 Swift 中,從 annotated APIs 返回的 Core Foundation 對象能夠自動進行內存管理--你不再需要調用自身的CFRetain,CFRelease,或者CFAutorelease函數。
如果你從自身的C函數和 Objective-C 方法中返回一個 Core Foundation 對象,為了自動引入內存管理,你需要用CF_RETURNS_RETAINED或者CF_RETURNS_NOT_RETAINED注釋這個對象。同樣你需要使用CF_IMPLICIT_BRIDGING_ENABLED和CF_IMPLICIT_BRIDGING_DISABLED包裹C函數聲明,這使得Core Foundation?????
Unmanned Objects 未托管對象
當Swift導入未注釋的APIs時,編譯器無法對返回的Core Foundation對象進行內存管理。Swift使用Unmanned<Instance>包裹這些對象。那些間接返回的對象也是難以管理的。例如:
CFStringRef StringByAddingTwoStrings(CFStringRef s1, CFStringRef s2)
對應的Swift:
func StringByAddingTwoStrings(_: CFString!, _: CFString!) -> Unmanaged! {
// ...
}
當你從 unannotated APIs 接收了一個難以管理的對象,在使用它之前,你必須要將它轉換為一個能夠內存管理的對象。在這方面,Swift 可以幫你進行內存管理而不用自己動手。同時,Unmanaged結構也提供了兩個方法來把一個難以管理的對象轉換為一個可內存管理的對象--takeUnretainedValue()方法和takeRetainedValue()方法。這兩個方法會返回原始的,開放的對象類型。您可以根據您實際調用的APIs返回的unretained或retained的對象,來選擇哪一方法更合適。
比如,假設這里有一個 C 函數,這個函數在返回值前不會釋放CFString對象。在使用這個對象前,您使用takeUnretainedValue()函數,以將它轉換為一個能夠內存管理的對象。
let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()
你也可以在一個非托管的對象中使用retain(),release()和autorelease()方法,但是這種做法并不值得推薦。
Unified Logging
統一的日志系統提供了一個API來捕獲所有等級的系統信息,同時他也是NSLog的替代品。
os.log?
可以指定log的等級:Info、Debug、Error