大きな事前ロードされたデータベースと小さなユーザーデータベース(両方の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ディレクトリに移動することもできます。私はそのアプローチが有効であることを確認していません。
アプリサンドボックスのユーザードキュメントディレクトリ(読み取り/書き込み)で、アプリのバンドル自体ではなく移行を行っていることを確認してください。 – Sunny
私はその(静的な)データをバックアップしてユーザのiCloudクォータに対してカウントさせたくないので、データをDocumentsディレクトリに移動したくなかった。しかし、iOS 5.0.1のように、バックアップされないファイルを指定する方法があります。http://developer.apple.com/library/ios/#qa/qa1719/_index.html – Aneel
さて、あなたは私にインスピレーションを与えました。私の問題を解決するために数時間を費やした後、私は[here](http://blog.atwam.com/blog/2012/05/11/multiple-persistent-stores-and-seed-data)の記事全文を書きました-with-core-data /)である。私はそれが将来他の人たちを助けることができると考えました。 – Wam