承接上一篇,當 NSPersistentStoreCoordinator
在做 addPersistentStoreWithType
時,會將 .sqlite
檔和 data model 做 ORM 的動作,可是如果該 .sqlite
內資料庫的資料和 data model 對不上的時候會怎樣?這種情況會發生在裝置已經安裝過 APP 了,而專案的 data model 有做了變更,使得 data model 和 .sqlite
的內容對不上,此時在預設自動產生的程式碼中,就會將錯誤列出來並呼叫 abort()
將 APP 結束
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
} catch {
// Report any error we got.
// ...
abort()
}
不解決了話, APP 要馬就是不能更新 data model,要馬就是瘋狂的 Crash…
解決方式就是做「資料轉換」(Migration),資料轉換有兩個層面,一個是實體 .sqlite
檔案中已經存在的 schema,另一個是 data model 版本的更新。最簡單做這個轉換設定的地方就在 options 這個參數,這個參數 Apple 提供了三個選擇
- NSIgnorePersistentStoreVersioningOption
- 這個選擇顧名思義就是完全不管資料對不對的起來,APP 可以成功啟動,但是因為實際上 data model 和
.sqlite
檔案立面的資料庫 schema 是有可能不同的,讀取時還可以用optional
來防止nil
,但是在寫入時非常容易 Crash。 - NSMigratePersistentStoresAutomaticallyOption
- 這個選項是叫系統「自動幫你做 Migration」,系統會去找對應的 Mapping File1,然後將舊的資料經過 Maggping File 的轉換轉成新版本的 data model 及將對應的欄位寫入更新後的
.sqlite
檔案中,但是如果找不到對應的 Mapping File,一樣會 Crash。 - NSInferMappingModelAutomaticallyOption
- 「自動生成 Mapping File」,系統幫你依照當前裝置內部 APP 的
.sqlite
版本和目前專案選擇的 data model 製作簡單的 Mapping File。
在網上很多 Migration 的文件當中都可以看到有一種叫做 lightweight migration 的方式,裡面都會說一些這種方法的限制,其實這種方法就是啟用NSMigratePersistentStoresAutomaticallyOption 和 NSInferMappingModelAutomaticallyOption 的選項,所以會「自動生成 Mapping File」和「自動做 Migration」,因為這種配對,當沒有 Mapping File 的時候會自動產生,而又會自動套用並執行 Migration,所以在剛接觸 Migration 的時候為了快速方便使用這種搭配,感覺上根本不需要去理會 Migration,其實說穿了並不是真的有輕重的差異,只是「自動」或「手動」做 Migration 而已,我個人的分類是「純自動」、「半自動」、「純手動」。
- 純自動: 就是 lightweight migration
- 半自動: 只啟動 NSMigratePersistentStoresAutomaticallyOption,而自己製作 Mapping file
- 純手動: 顧名思義就是給
nil
然後通通自己來,有好有壞
從官方的參考文件中大概可以看出「純自動」的 Mapping File 是依據怎樣的原則,以資料庫的講法來看了話類似這樣…
- 新增欄位 ( Simple addition of a new attribute )
- 移除欄位 ( Removal of an attribute )
- 將非空欄位改成可為空 ( A non-optional attribute becoming optional )
- 一個可為空的欄位變為非空並且指定預設值 ( An optional attribute becoming non-optional, and defining a default value )
- 欄位或資料表重新命名 ( Renaming an entity or property )
- 新增或移除外鍵 ( You can add a new relationship or delete an existing relationship )
- 外鍵關聯重新命名 ( Renaming a relationship )
- 改變關聯結構 ( Adding relationships and changing the type of relationship)
- 改變資料表繼承關係 ( Changing the entity hierarchy )
所以以上是系統可以幫開發者「自動」處理的部分,但是如果需要做的轉換是超出以上範圍的,例如 v1 有個欄位叫做 fullname,但是在 v2 的時候想要把 fullname 依照空格拆成 firstname 和 lastname,類似這種的就無法使用自動轉換
ps. 如果是用「半自動」的方法就可以做到這種轉換
- Mapping File 是一個在 data model 在做轉換時需要參考的檔案,裡面會設定系統在兩個版本的 data model 中各欄位要做怎樣的對應 ( Mapping Policy ) ↩
沒有留言:
張貼留言