ポジティブ丸メガネ

3年目エンジニアです。

SwiftのCoredata(データベース)のマイグレーションで少し苦労した。

作成しているアプリでCoredataのAttributeを増やす必要が出てきました。こういった場合、単純にAttributeを増やしてアプリを実行すると、アプリはクラッシュしてしまいます。ですのでCoredataのマイグレーションを行う必要がありますが、少し詰まったので忘れないように残しておきます。

Androidアプリを作成していた頃に、マイグレーションを行った時は非常にめんどうだったので、結局DBを消して無理やり解決していました。今回もそうすれば動くには動くのですが、自分ですでにアプリをそこそこ使っていて、DBをリセットされるのはちょっと残念だったので頑張ってみることにしました。

こちらのサイトを参考にして、行いました。
Core DataでDBのMigrationを行う。 |
こちらのサイトの通りにやっていた(つもり)のですが、下記エラーがでて動きません。

「The managed object model version used to open the persistent store is incompatible with the one that was used to create the persistent store」

ふむ。結構いろいろ調べてみたのですが、大体はDB消してもう一回やれよという強引な解決策がほとんどでした。

もう一度AppDelegateをよくよく見てみると、間違い発見!
try coordinator.addPersistentStoreWithType()のoptionの引数がnilになっていました。元々初期値はnilだったので、治すのを忘れていました。せっかくoptions作ったのに参照してないとかアホすぎでしたね。一応下記に該当部分を載せておきますね。

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and return 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."
        
        let options = [NSMigratePersistentStoresAutomaticallyOption: true,NSInferMappingModelAutomaticallyOption: true]
        
        do {
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options)
        } 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
    }()

まあともかくこれでアプリを実行すると無事マイグレーションが行われていたので、一件落着。