为了方便使用,Swift 的基本类型都可以无缝转换到 Foundation 框架中的对应类型。

因为 Cocoa 框架所接受和返回的基本数据类型都是自身框架内的类型,也就是 Foundation 中所定义的像 NSStringNSNumberNSArray 等这些东西。而脱离 Cocoa 框架进行 app 开发是不可能的事情。因此我们在使用 Swift 开发 app 时无法避免地需要在 Swift 类型和 Foundation 类型间进行转换。如果需要每次显式地书写转换的话,大概就没人会喜欢用 Swift 了。还好 Swift 与 Foundation 之间的类型转换是可以自动完成的,这使得通过 Swift 使用 Cocoa 时顺畅了很多。

这个转换不仅是自动的,而且是双向的,而且无论何时只要有可能,转换的结果会更倾向于使用 Swift 类型。也就是说,只要你不写明类型是需要 NS 开头的类型的时候,你都会得到一个 Swift 类型。这类转换有下面的对应关系:

  • String - NSString
  • Int, Float, Double, Bool 以及其他与数字有关的类型 - NSNumber
  • Array - NSArray
  • Dictionary - NSDictionary

举个例子,

import Foundation

let string = "/var/controller_driver/secret_photo.png"
let components = string.pathComponents

string 在 Swift 中是被推断为 String 类型的,但是由于我们写了 import Foundation,因此我们可以直接调用到 NSString 的实例方法 pathComponents。在 Foundation 中,pathComponents 返回的应该是一个 NSArray,但是如果我们检查这里的 components 的类型 (使用 components.dynamicType),会发现它是一个 [String]。在整个过程中我们没有写任何类型转换的代码,一切都这么静悄悄地就发生了。

如果我们出于某种原因,确实需要 NSString 以及 NSArray 的话,我们需要显式的转换:

import Foundation

let string = "/var/controller_driver/secret_photo.png"

let components_ = string.pathComponents as NSArray
let fileName_ = components_.lastObject as! NSString

components_.dynamicType //_SwiftDeferredNSArray.Type
fileName_.dynamicType   //__NSCFString.Type

一般情况下当然是不需要这么多此一举的。

有一个需要注意的问题是 ArrayDictionary 在行为上和它们对应的 NS 模式的对应版本有些许不同。因为 Swift 的容器类型是可以装任意其他类型的,包括各种 enumstruct,而 NSArrayNSDictionary 只能放 NSObject 的子类对象。所以在 ArrayDictionary 中如果装有非 AnyObject 或者不能转为 AnyObject 的内容的话,做强制的转换将会抛出编译错误 (这要感谢 Swift 的强类型特性,我们可以在编译的时候就抓到这样的错误)。