注重安全的swift中變量聲明時要表明是否可變,不變用<code>let</code>,可變用<code>var</code>。然而由于swift設計之初就要考慮兼容OC的這個歷史包袱,很多類型都沿用了OC的類型。只有幾個基礎類型重寫聲明成了值類型(struct),比如:<code>String</code>,<code>Array</code>。
引用類型的<code>let</code>和值類型的<code>let</code>在邏輯上有著根本的不同。值類型的不可變就如字面意義,數據不能被更改;而引用類型的不可變只要保證指向的實例不變就可以了,實例本身的屬性是可以改變的。
一些原有的OC的foundation表示數據的引用類型在swift的行為就和期待的不同了,比如:
let date = NSDate()
date.addingTimeInterval(1000)
這樣的寫法是可以編譯通過的。然而確和我們期望的結果不同。我們聲明了一個不可變的日期,然而在<code> addingTimeInterval </code>后日期已經被改變了。
所以在3.0中把原有的很多表示數據的引用類型在增加了對應的值類型。
更改的如下:
Value Type | Class Type |
---|---|
AffineTransform | NSAffineTransform |
CharacterSet | NSCharacterSet, NSMutableCharacterSet |
Date | NSDate |
DateComponents | NSDateComponents |
Data | NSData, NSMutableData |
IndexSet | NSIndexSet, NSMutableIndexSet |
IndexPath | NSIndexPath |
Notification | NSNotification |
PersonNameComponents | NSPersonNameComponents |
URL | NSURL |
URLComponents | NSURLComponents |
URLQueryItem | NSURLQueryItem |
UUID | NSUUID |
在swift中相關的api返回類型也做了對應的更改。比如常見的<code> cellForRow </code>方法:
func cellForRow(at indexPath: IndexPath) -> UITableViewCell?
原來的參數類型是NSIndexPath,現在則改為了IndexPath。
和原來的OC的類型映射和原來的邏輯一樣,類型轉換直接使用<code> as </code>
let ocString = NSString(string: "xxx")
let swiftString: String = ocString as String
let swiftIndex = IndexPath(row: 1, section: 1)
let ocIndex = swiftIndex as NSIndexPath
需要強調的是,兩者之間的轉換是有成本的。swift中并沒有真正完全的實現一套數據存儲邏輯。只是內部保存了對oc對象的引用,使得swift api訪問時行為邏輯和值類型一致,包括copy on write。
如下圖所示,當執行<code> var otherData = data </code>后,其實指向的是同一個引用類型的實例。
歡迎關注我的微博:@沒故事的卓同學