fb-script

2016年9月9日 星期五

CoreData with swift 2 筆記 - Migration (1) 「全自動」lightweight migration

承接上一篇,當 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. 如果是用「半自動」的方法就可以做到這種轉換


  1. Mapping File 是一個在 data model 在做轉換時需要參考的檔案,裡面會設定系統在兩個版本的 data model 中各欄位要做怎樣的對應 ( Mapping Policy )

沒有留言:

張貼留言