2012-04-19 4 views
11

大きな事前ロードされたデータベースと小さなユーザーデータベース(両方のCoreData SQLiteストア)を持つiOSプロジェクトがあります。以前の質問では、構成を使用して、どのエンティティをどのストアで使用するかを制御することが推奨されています。私はそれをうまく動作させるのに問題があります。ここで複数のストアを持つCoreData:設定の問題

- (NSManagedObjectModel *)managedObjectModel 
{ 
    if (_managedObjectModel != nil) return _managedObjectModel; 
    // set up the model for the preloaded data 
    NSURL *itemURL = [[NSBundle mainBundle] URLForResource:@"FlagDB" withExtension:@"momd"]; 
    NSManagedObjectModel *itemModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:itemURL]; 
    // set up the model for the user data 
    NSURL *userDataURL = [[NSBundle mainBundle] URLForResource:@"UserData" withExtension:@"momd"]; 
    NSManagedObjectModel *userDataModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:userDataURL]; 
    // merge the models 
    _managedObjectModel = [NSManagedObjectModel modelByMergingModels:[NSArray arrayWithObjects:itemModel, userDataModel, nil]]; 
    // define configurations based on what was in each model 
WRONG [_managedObjectModel setEntities:itemModel.entities forConfiguration:@"ItemData"]; 
WRONG [_managedObjectModel setEntities:userDataModel.entities forConfiguration:@"UserData"]; 
    return _managedObjectModel; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    if (_persistentStoreCoordinator != nil) return _persistentStoreCoordinator; 
    // preloaded data is inside the bundle 
    NSURL *itemURL = [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"FlagDB.sqlite"]; 
    // user data is in the application directory 
    NSURL *userDataURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"UserData.sqlite"]; 

    NSManagedObjectModel *mom = self.managedObjectModel; 
    NSError *error = nil; 
    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 

    if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"ItemData" URL:itemURL options:nil error:&error]) 
    { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 
    ... 

が...私がしようとしてきたものだこれは、「店を開くために使用されるモデルは、ストアを作成するために使用したものと互換性がない」と中止します。モデルのハッシュをストア内のハッシュに対してチェックすると、ItemData設定内にあるエンティティと同じであることが示されます。

私はそうのように、軽量な移行をやってみた場合:

それはNSInvalidArgumentException '理由で失敗
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 
    if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"ItemData" URL:itemURL options:options error:&error]) 

:「 『にItemData』モデルは、コンフィギュレーションが含まれていません」私は軽量の移行プロセスによって新しいモデルが作成されており、自分の構成が含まれていないためです。

他のスレッドのいくつかの提案に基づいて、構成なしで軽量な移行を行い、その構成を使用して新しいコーディネータを作成しようとしました。このような仕組みですが、ユーザーデータエンティティ(そこに属していない)に対応するプリロードされた.sqliteファイルにテーブルを追加し、新しく作成されたユーザーデータストアに事前ロードされたデータテーブルとユーザーデータテーブルの両方を作成します。最終的な結果は、間違った店舗を探しているので一見フェッチが失敗するということです。

NSDictionary *migrationOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 

// make a temp persistent store coordinator to handle the migration 
NSPersistentStoreCoordinator *tempPsc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 
// migrate the stores 
if (![tempPsc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:itemURL options:migrationOptions error:&error]) 
{ 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 
if (![tempPsc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:userDataURL options:migrationOptions error:&error]) 
{ 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 

// make a permanent store coordinator 
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 

NSDictionary *readOnlyOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSReadOnlyPersistentStoreOption, nil]; 
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"ItemData" URL:itemURL options:readOnlyOptions error:&error]) 
{ 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 

/*if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"UserData" URL:userDataURL options:nil error:&error]) 
{ 
NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
abort(); 
}*/ 

そして後で...

OSAppDelegate *delegate = [UIApplication sharedApplication].delegate; 
    NSManagedObjectContext *context = delegate.managedObjectContext; 
    // sanity check 
    for (NSPersistentStore *store in context.persistentStoreCoordinator.persistentStores) { 
     NSLog(@"store %@ -> %@", store.configurationName, store.URL); 
     NSMutableArray *entityNames = [[NSMutableArray alloc] init]; 
     for (NSEntityDescription *entity in [context.persistentStoreCoordinator.managedObjectModel entitiesForConfiguration:store.configurationName]) { 
      [entityNames addObject:entity.name]; 
     } 
     NSLog(@"entities: %@", entityNames); 
    } 

    NSFetchRequest *categoryFetchRequest = [[NSFetchRequest alloc] init]; 
    categoryFetchRequest.entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context]; 
    categoryFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", categoryName]; 
    NSError *error = nil; 
    Category *category = [[delegate.managedObjectContext executeFetchRequest:categoryFetchRequest error:&error] lastObject]; 

これは私が二店の追加のコメントを解除するまで、適切な名前のCategoryオブジェクトを返し、正常に動作します。もし私がそれを行うと、フェッチの結果は空に戻ります。診断NSLogメッセージは私が期待しているものを正確に表示します。各ストアは正しい構成に関連付けられており、各構成には適切なエンティティがあります。

マルチプルストア設定のソースコードで誰かが私を指摘することができますか、私が間違っていることを私に教えてください。前もって感謝します!


を解決しよう:問題の核心は、2行は最初のコードリストで間違っマークされました。私はプログラムで構成を作成しようとしていましたが、それは不十分なようです。これを行った後でコンフィグレーションのManagedObjectModelをクエリすると、doが実際にリストのコンフィグレーションを参照し、正しいエンティティがコンフィグレーションに関連付けられます。しかし、PersistentStoreCoordinatorがそれらを適切に使用できるようにするために何か他のものを実行する必要があるようです。 Xcodeで設定を作成すると、それらが機能します。


UP FOLLOW:余分な思わぬ障害があります。最後のPersistent Store Coordinatorを設定する前に、個別の移行パスを実行するソリューションは、シミュレータでうまくいきます。実際のデバイスでは、アクセス許可が厳しくなっています。この移行を実行しようとすると、Appバンドル内のストアが読み取り専用なので失敗します。モデルを統合しない限り、移行が必要なように見えます。モデルが1つしかなく、Appバンドル内のストアが互換性がある場合、移行は不要であり、Xcodeで定義された設定を使用したアクセスが機能します。

移行を試行する前に、データをDocumentsディレクトリに移動することもできます。私はそのアプローチが有効であることを確認していません。

+0

アプリサンドボックスのユーザードキュメントディレクトリ(読み取り/書き込み)で、アプリのバンドル自体ではなく移行を行っていることを確認してください。 – Sunny

+0

私はその(静的な)データをバックアップしてユーザのiCloudクォータに対してカウントさせたくないので、データをDocumentsディレクトリに移動したくなかった。しかし、iOS 5.0.1のように、バックアップされないファイルを指定する方法があります。http://developer.apple.com/library/ios/#qa/qa1719/_index.html – Aneel

+2

さて、あなたは私にインスピレーションを与えました。私の問題を解決するために数時間を費やした後、私は[here](http://blog.atwam.com/blog/2012/05/11/multiple-persistent-stores-and-seed-data)の記事全文を書きました-with-core-data /)である。私はそれが将来他の人たちを助けることができると考えました。 – Wam

答えて

5

両方の設定を同じモデル(つまり同じmomd)で定義しようとしましたか?これは、データモデルの1つを編集しながら、「エディタ - >構成の追加」を選択することで簡単に行うことができます。 UserDataとItemDataのエンティティを適切な設定にドラッグします。このように指定された設定は、Core Dataが尊重するものです。ファイル/ URLの名前ではありません。上記の作業を終えたら、上記の_managedObjectModelを単純化して、それが呼び出されるたびに単一のmomdファイル/ URLを探します。

また、2つの別々のmomdファイルを保持することにした場合は、それぞれのモデル定義ファイルの "UserData"と "ItemData"という名前の構成で実際にモデルを定義していることを確認してください。

私の最初の提案は、1つのモデルファイルを保持することです。これらの構成が同じオブジェクトモデルに存在することができない理由がない限り、複数のファイルを使用することは複雑になりません。私は、あなたが上でやっていることをコア・データがうまくやっていくのはかなり難しいと思う。コードのモデリング部分を単純化してみてください。

+1

返事をありがとう。私は2つの別々のモデルを使用する正当な理由があります。アイテムデータモデルは、別のプロジェクト(データセットの作成/編集に使用されたOS Xアプリケーション)と共有されます。可能であれば、私は2つのモデルを別々に保つことができるようにしたいと思います。 – Aneel

+1

私はあなたが提案したことを試して、それは動作します。 ユーザーデータモデルをアイテムデータモデルにコピーし、XCodeで2つの構成を作成しました。私は一時的なPSCを作成し、データストアごとに構成のない軽量な移行を行い、別のPSCを作成し、各ストアを適切な構成で追加する必要があります。それらのステップがなければ、私はまだエラーが発生します。それらを使用して、PSCは各エンティティを正しいストアに関連付けます。 統合されたモデルは、2つの別々のMOM/PSC/MOCを持つ私の他の解決策に比べると控え目ではないと思います。ありがとう!私はまだ2つの別々のモデルでこれを行う方法が好きです。 – Aneel

+1

さて、私はあなたがモデルを分離しておくことを提案したことも試みました。それも動作します!私の問題の中核は、ManagedObjectModel addEntities:forConfiguration:を使ってプログラムで設定を定義することは機能しないということでした。 MOMに設定を照会すると表示されますが、実際にはPSCによって正しく使用されていないようです。 Xcodeで設定を作成すると、舞台裏でより多くのことを行う必要があります。 – Aneel

関連する問題