Core Data Migration--Core Data輕量級遷移

  • 背景:

    • 我們的APP只需要在用戶登錄的時候存儲一些關鍵的數據,數據量不大。其余數據在線請求就行,也沒有涉及大量的數據存儲,用Core Data 還挺方便的
    • 當我要發布企業1.2版本的時候,發現因為用了CoreData進行數據的存儲,當我修改了里面的Model的時候。比如


      CoreData里面的Model
  • 當我添加或者修改一個字段或者是添加另外一個model的時候。我們會遇到兩個問題

    • 1.運行到真機:會報錯,需要卸載APP后再運行重裝
    • 2.發布版本后,你無法覆蓋安裝而且會出錯。安裝不了


      **reason = "The model used to open the store is incompatible with the one used to create the store";**
  • 而遇上這樣的問題肯定不行,用戶用不了你就掛了。所以我們要做版本的數據遷移




  • Why Make Core Data Migrations?
    However there is a problem. Core Data expects a consistent schema. Meaning that if we add or remove entities, attributes, or change their types, it will cause a conflict. This means that if you:1) Store some data inside of an app using a set schema. For example a Model named LogItem with a title(String) attribute.2) Change any of the schema. For example add a new full title attribute to become ‘fullTitle’.3) Run the app again
    There will be a conflict, and the app will do a hard crash. This includes anyone who has downloaded your app from the app store! Not only that, if you change the text attribute, and you don’t perform any kind of migration, you will be risking losing user’s data. If you want people to uninstall your app, this is a fantastic way to make that happen.
    • 也就是我們上面遇上的問題:當你在swift中使用了CoreData,CoreData是需要一個始終如一的模式。如果你修改了添加或者移除了任何一個實體屬性或者修改了類型。就會造成沖突。就會導致運行的時候你的APP崩潰,或者別人在AppStore上下載你的APP后直接崩潰閃退,這是很嚴重的問題,丟失用戶可能是致命問題
  • 創建一個遷移Migration--Create A Migration
    • 沒創建遷移前Xcode會在AppDelegate中為我們自動創建下面的代碼。但是Xcode并沒有給出任何的可選的遷移。但是它有一個persistentStoreCoordinator。它是專門負責遷移的發生。我們只需要關注options。它是一個字典,是一個遷移字典Migrations Options
      • NSMigratePersistentStoresAutomaticallyOption sounds pretty nice. Automatic migration? Sign me up!
      • NSInferMappingModelAutomaticallyOption will create the mapping model, while
      • NSMigratePersistentStoresAutomaticallyOption will perform the migration.
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
        } catch {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason

            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }
        
        return coordinator
    }()
  • 所以我們添加
    let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
        NSInferMappingModelAutomaticallyOption: true]
    if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions, error: &error) == nil {
  • 創建遷移后是:
    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
                            NSInferMappingModelAutomaticallyOption: true]
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
        } catch {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason
            
            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }
        
        return coordinator
    }()
  • 也就是說,我們添加了:
            let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
                            NSInferMappingModelAutomaticallyOption: true]
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
  • 這樣基礎的操作,是讓我們的Core Data去嘗試讓我們的Models在不同的版本之間自動合并以及映射

  • 但是這樣還是不夠,我們還需要接下來的操作

  • 添加一個Model版本--Add a Model Version

  • 先要選上你的Core Data model,然后在工程的導航欄部分-->Editor-->Add Model Version(不選上,不會出現這個)

Add Model Version
Model Virsion
  • 名字可以隨便起,但是建議最好叫xxxV2/3/...便于區分,因為你每遷移或者增加Model一次就產生了一次新的Model Schema.每次都會變的哦
  • 然后我們就要Model Virsion2成為我們的可用的Model.選中Core Data model。然后:
ModelV2成為最新的可用的Model
對應Model文件中修改一下
  • 這樣你就可以在MedelV2中修改你想修改的了,APP運行和發布后也就不會出錯了

  • 重要的幾點:

    • 1.設置好options
    • 2.添加新的Model Virsion
    • 3.選好新的Model Virsion
  • 猜測的幾點

    • 1.每次大的修改Model都要添加新的Model Virsion.版本不停往上
    • 2.修改哪怕是退回去的時候,也最好是新建一個新的Model Virsion,刪除不想要的
    • 3.有些還需要我去繼續驗證



蘋果產品對應架構
  • 在項目中遇上了一個Swift中的一個坑:當APP發版后,有用戶發現他的iPhone5和5c裝上APP點擊登錄后直接崩潰閃退。其余的手機沒有問題。首先我以為是我們SDK支持的架構不支持ARMv7s,但是問清楚后發現是支持4s往上的。所以問題肯定出現在自己的程序中。查看崩潰日志(查看崩潰日志的工具Log Guruhttp://club.fir.im/topic/54daf35374c4c85e73e4aaba)。
    發現是自己有一個必須用到的參數id的問題
曾經我的id一直是Int64
  • 這里的問題是:Swift是強語言,類型要求十分嚴格。我在Core Data里用了一個Integer64,然后Swift代碼里面寫的是Int。最后導致程序不能安裝(iPhone5和5c的CPU是32位的,所以要用Int32向上兼容。這里就用到了上面數據的遷移將它改成Int32,也不會出問題了)如果是已經上架AppStore的話,5和5c用戶就等下一個版本吧。。。我也就分分鐘去財務了
吐槽:Swift編譯時間好長。。。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容