注重安全的swift中變量聲明時要表明是否可變茄蚯,不變用<code>let</code>,可變用<code>var</code>。然而由于swift設(shè)計之初就要考慮兼容OC的這個歷史包袱,很多類型都沿用了OC的類型梁肿。只有幾個基礎(chǔ)類型重寫聲明成了值類型(struct)蛤迎,比如:<code>String</code>,<code>Array</code>确虱。
引用類型的<code>let</code>和值類型的<code>let</code>在邏輯上有著根本的不同。值類型的不可變就如字面意義替裆,數(shù)據(jù)不能被更改校辩;而引用類型的不可變只要保證指向的實例不變就可以了,實例本身的屬性是可以改變的辆童。
一些原有的OC的foundation表示數(shù)據(jù)的引用類型在swift的行為就和期待的不同了宜咒,比如:
let date = NSDate()
date.addingTimeInterval(1000)
這樣的寫法是可以編譯通過的。然而確和我們期望的結(jié)果不同把鉴。我們聲明了一個不可變的日期故黑,然而在<code> addingTimeInterval </code>后日期已經(jīng)被改變了。
所以在3.0中把原有的很多表示數(shù)據(jù)的引用類型在增加了對應(yīng)的值類型庭砍。
更改的如下:
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中相關(guān)的api返回類型也做了對應(yīng)的更改场晶。比如常見的<code> cellForRow </code>方法:
func cellForRow(at indexPath: IndexPath) -> UITableViewCell?
原來的參數(shù)類型是NSIndexPath,現(xiàn)在則改為了IndexPath怠缸。
和原來的OC的類型映射和原來的邏輯一樣诗轻,類型轉(zhuǎn)換直接使用<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
需要強調(diào)的是,兩者之間的轉(zhuǎn)換是有成本的凯旭。swift中并沒有真正完全的實現(xiàn)一套數(shù)據(jù)存儲邏輯概耻。只是內(nèi)部保存了對oc對象的引用使套,使得swift api訪問時行為邏輯和值類型一致,包括copy on write鞠柄。
如下圖所示侦高,當(dāng)執(zhí)行<code> var otherData = data </code>后,其實指向的是同一個引用類型的實例厌杜。
歡迎關(guān)注我的微博:@沒故事的卓同學(xué)
相關(guān)鏈接:
SE0069-Mutability and Foundation Value Types