コアデータでの複数の永続ストアの使用

すべてのiOS(およびMAC OS X)開発者は、Core Dataなどのシステムフレームワークを認識しています。 このギズモはかなり強力なORMです(少なくともモバイルプラットフォームの場合)。



当初、アプリケーションは、アプリケーションに保存する必要があるすべての情報に対して1つのデータベースを使用していました。 しかし、機能が大きくなるにつれて、いくつかのエンティティを異なるデータベース、または異なるタイプの永続ストアに配置する方が論理的であることが明らかになりました。 詳細には触れませんが、主なことは、最初はモノリシックなNSSQLiteStoreをいくつかに分割する必要があったことです。



ドキュメントはこの問題を非常に不十分にカバーしています。 1つのNSPersistentStoreCoordinator内で複数のNSPersistentStoreを使用でき、さらに1つのNSManagedObjectContextから直接使用できると言われています。 素晴らしいですね。

Appleドキュメントだけで問題を理解するために必死で、私はGoogleに切り替えなければなりませんでした。 主にStack Overflowエリアでネットワークの広がりをさまよい、多くの情報を収集しましたが、Xcodeとの数時間の戦争の後、あまり効果のないソリューションを得ました。 この問題を研究する過程で、次のことが明らかになりました。



実際、複数のNSPersistentStoreからの情報は、1つのNSManagedObjectContextで収集できます。 これに関する詳細な記事があり、プラグインをCore Dataを使用してアプリケーションに接続するメカニズムについて説明しています。 ここで見つけることができますwww.cimgf.com/2009/05/03/core-data-and-plug-ins



1つのNSManagedObjectContextに対応できるのは、1つのNSManagedObjectModelのみです。 どのストレージにどのエンティティを保存するかを指定する方法は? これは、構成名を使用して行われます。 1つのNSManagedObjectModelで構成のセットを作成することも、複数のNSManagedObjectModelを使用して1つにストンプすることもできます(各構成を作成するには、名前付き構成を作成する必要があります)。



-(NSManagedObjectModel*)managedObjectModel; { if(managedObjectModel)return managedObjectModel; NSBundle*myBundle =[NSBundle bundleForClass:[self class]]; NSArray*bundles =[NSArray arrayWithObject:myBundle]; managedObjectModel =[[NSManagedObjectModel mergedModelFromBundles:bundles] retain]; return managedObjectModel; }
      
      







NSManagedObjectModelを準備(ステインまたは事前作成)した後、関数を使用してコーディネーターにリポジトリを追加できます。

 - (NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType configuration:(NSString *)configuration URL:(NSURL *)storeURLoptions:(NSDictionary *)options error:(NSError **)error
      
      





各ストレージタイプの構成名を使用します。 このようなもの:

  NSPersistentStore * store = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:CONFIG_NAME URL:databaseURL options:options error:&error];
      
      





リポジトリを含むファイルが自動的に作成されます。 目標が達成された後、Core Dataがそこに作成したストレージを自分の目で見たかったのです。 具体的には、虫眼鏡の下で、NSSQLiteStoreが検討されました。 それは興味深いことでした-ファイルの構成名が何であっても、オブジェクトモデルのすべてのエンティティに対してラベルが作成されます。 ただし、構成で指定されているエンティティはファイルに書き込まれます。 それ以外の場合、NSManagedObjectModelエンティティが実際に異なるベースに押し込まれているため、すべてが魔法のように機能しました。



それとは別に、ストレージの接続について言わなければなりません。 異なるリポジトリのエンティティ間の関係を作成することはできません。 ただし、取得したプロパティは使用できます。 これは一般に、 developer.apple.com / library / mac /#documentation / Cocoa / Conceptual / CoreData / Articles / cdRelationships.html#// apple_ref / doc / uid / TP40001857-SW5のAppleドックで多少明確に説明されています。



しかし、それだけではありません。 古いバージョンのアプリケーションは、唯一のデータベースに多数の有用なデータを保存していたため、この情報を新しいリポジトリに何らかの形で移行したかったのです。 これを行うために、NSPersistentStoreCoordinatorカテゴリーにこのようなものを走り書きしました



 - (BOOL)migratePersistentStore:(NSURL *)sourceStoreURL withType:(NSString *)sourceType to:(NSURL *)destinationStoreURL type:(NSString *)destinationType andAddWithConfiguration:(NSString *)configuration { NSError *error = nil; NSDictionary *sourceMetadata = [self.class metadataForPersistentStoreOfType:sourceType URL:sourceStoreURL error:&error]; if(sourceMetadata==nil) return NO; NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:sourceMetadata]; NSMigrationManager *migrationManager = [[[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:self.managedObjectModel] autorelease]; NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:nil forSourceModel:sourceModel destinationModel:self.managedObjectModel]; if(mappingModel==nil) return NO; BOOL result = [migrationManager migrateStoreFromURL:sourceStoreURL type:sourceType options:nil withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:destinationType destinationOptions:nilerror:&error]; if(result==NO) return NO; NSLog(@"Successful DB migration"); NSDictionary *options = [self.class migrationOptionsWithAutoMigration:NO]; NSPersistentStore * addedStore = [self addPersistentStoreWithType:destinationType configuration:configuration URL:destinationStoreURL options:options error:&error]; return addedStore!= nil; }
      
      





残念ながら、この方法では1つのデータベースを複数のデータベースに分解できませんでした。 メソッドの最初の呼び出しはバタンと鳴ります。 ただし、2番目の呼び出しでは、既に別の構成名で、悲惨なことにCore Dataは「同じストアを2回追加することはできません」と言っています。 その結果、重要なデータが保存されている構成のみを移行し、ゼロから再構築できるログとキャッシュからデータベースを作成することにしました。




All Articles