Core Dataがモデルを自動的に移行するために何をしなければなりませんか?


96

コアデータモデルの自動/軽量移行に関するドキュメントを読みましたが、実装に問題があります。

私が理解しているように、アプリケーションは、そのモデルとデバイス上に既に存在するモデルが同じではないことに注意する必要があります。属性または関係と同様の単純な変更のみを追加した場合、モデルは自動的にアップグレードされます。

ポインタ-Xcodeで何かを設定する必要がありますか?

回答:


138

これは非常に単純であることがわかりました。

私のAppDelegateでNSPersistentStoreCoordinatorをセットアップしました。これにいくつかのオプションを追加して、自動移行を処理するように指示する必要があります。

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

次に、xCodeで少しトリックを行う必要があります。

  1. xcdatamodelファイルを選択します
  2. 上部の[デザインメニュー]を選択し、次に[データモデル]を選択して、[モデルバージョンの追加]を選択します。
  3. xcdatamodelファイルは、xcdatamodelファイルと同じ名前で、拡張子がxcdatamodeldの新しいディレクトリに移動されます。このディレクトリには、名前に2が付いた2番目のファイルがあります。新しいファイルを選択してから、デザイン->データモデル->現在のバージョンを設定(Xcode 4ではこれを行います
  4. プロジェクトに互換性がない原因となった変更を既に加えている場合は、これらの変更を元のxcdatamodelファイルから取り出します。まだ変更を加えていない場合は、2.xcdatamodelファイル(現在のバージョンを作成したファイル)を編集してください。
  5. これで、古いバージョンのデバイスにこのバージョンをインストールすると、そのモデルが新しいモデルに自動的にアップグレードされます。

これは素晴らしく、私が望んだように単純に見えますが、モデルを変更するときは開発中に注意する必要があると思います-そうでない場合は、変更ごとに新しいバージョンを作成する必要があります。

変更したファイルをすべて保持し、更新を展開する準備ができたら、中間のファイルをすべて削除して、最も古い最新のモデルで展開することになると思います。


更新(2011年7月15日):

Appleで更新されたドキュメントがあることを指摘してくれた@ rockstarberlinに感謝します。

Xcode 4:管理対象オブジェクトモデルの現在のバージョンを設定する

更新:2013年8月19日、より良いリンク:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html


Xcodeのドキュメントビューアとdeveloper.apple.comから入手できるCore Data Migration and Versioning Guideを読むことをお勧めします。
ハンター

1
私はそこに答えを見つけることができませんでした。単純にレイアウトされています。これを行う方法を見つけるのにしばらく時間がかかりました。
Grouchal 2009年

NSInferMappingModelAutomaticallyOptionは適切に機能しますが、属性の名前を変更するような単純なマッピングの場合のみです。より複雑なもの(関係、エンティティの削除または追加)の場合は、マッピングモデルを追加する必要があります。XcodeがNSInferMappingModelAutomaticallyOptionが宣言されていないと不平を言った場合は、#import <CoreData / CoreData.h>をアプリのデリゲートヘッダーファイルに追加します。
Elise van Looij

モデルにいくつかのエンティティを追加し、悪名高い「ストアを開くために使用されるモデルは、ストアを作成するために使用されるものと互換性がありません」というエラーが発生しました。あなたの解決策はそれを修正しました!どうもありがとうございました!
Karsten Silz 2010年

1
これらの手順を実行した後に「2つの異なるエンティティを持つモデルをマージできない」というエラーが発生する場合は、下記のSantthoshの回答を参照してください。
benvolioT 2010年

14

これは非常に役に立ちました。Appleのドキュメントは-いつものように-ものすごく不完全だった。これらの変更を行った後、最初に実行したときに「2つの異なるエンティティxxxを持つモデルをマージできません」というエラーが発生したため、クリーンビルドを実行することをお勧めします。クリーンビルドで修正されました。


クリーンビルドは私の問題も修正しました。
jrainbow 2009

6

Grouchalの答えは完璧です...しかし、ビルドを数回クリーンアップした後でも「2つの異なるエンティティxxxを使用してモデルをマージできない」場合は... managedObjectModelのロード方法に問題がある可能性があります。これを見てください...これは修正に役立ちました。

コアデータ移行の問題


3

また、私がしたように、この投稿を偶然見つけた場合、「ストアを開くために使用されたモデルは、ストアを作成するために使用されたモデルと互換性がありません」というエラーが発生し、シミュレーターを使用してデバッグしていて、完全に置き換えたいと思っています。古いモデルがインストールされている場合は、シミュレーターアプリをリセットするか、アプリをシミュレーターから削除すると、おそらく同様に機能します。

ここの投稿を読むまで、これを試すことはありませんでした。その時点で、アプリをシミュレーターにインストールし、その後モデルを変更したため、前述のランタイムエラーが発生していることに気付きました。


1

Santthoshの回答をフォローアップするために、代わりにここにコードスニペットを投稿すると思いました。あなたはmanagedObjectModelを作成する必要がありますinitWithContentsOfURL:mergedModelFromBundles:そうしないとエラーが発生代わりにます。

2つの異なるエンティティXXXとXXXを持つモデルをマージすることはできません

モデルファイルの名前が「モデル」の場合、managedObjectModelを作成する方法は次のとおりです。

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 

このブログ投稿のクレジット。



1

私は何年もこの問題を抱えてきましたが、これらすべての答えを試しても無駄になりました。今日、私はついに自分が間違っていることを理解しました。非常に単純な問題ですが、見落としました。新しいバージョンのデータモデルを作成するときに、列を追加する場合は、それらをオプションとしてマークしてください。そうしないと、新しい列の値が入力されないため、単純な移行は機能しません。

新しい列に「オプション」がチェックされていることを確認したらすぐに、もう一度移行を試みましたが、うまくいきました。


1

別の問題が原因でこの投稿に遭遇しましたが、エラーは次のとおりでした。「ストアを開くために使用されたモデル構成は、ストアの作成に使用されたものと互換性がありません。

ここに私の問題とその解決策がありました。私のモデルでは、設定使用していました。エンティティの一部を1つのファイルに保存し、他のエンティティを別のファイルに保存しました。(私は定期的にダウンロードする必要があるかもしれないいくつかのデフォルトを持っています、そしてそれらを全体にマージすることは信じられないほどの苦痛でしょう)。とにかく、私は新しい実体を作りました。プログラムは正常に動作しているように見えましたが、終了すると必ず上記のエラーが発生しました。

そこでの解決策は、私の構成を見て、現在どの構成にも含まれていないエンティティがあることに気づき、それを1つに追加することでした。夢のように走ります。

これはOPの問題を修正しません。しかし、たぶんグーグル経由でここに着いた欲求不満な人が私が乗っていたボートに乗ることになるでしょう:)


0

iOS 4.0以降

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

0

上記の@GrouchalのXcodeバージョン5のすばらしい説明を少し編集します。

旧:2.上部の[デザインメニュー]を選択し、次に[データモデル]を選択して、[モデルバージョンの追加]を選択します。

バージョン5+:2. [エディター]メニューを選択し、[モデルバージョンの追加...]を選択して、バージョン名を入力し、[モデルに基づく](リストから元のモデルを選択)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.