web-dev-qa-db-ja.com

1つのオブジェクトモデルで複数(2)の永続ストアを使用しながら、一方から他方への関係を維持できますか?

はじめに

私のiOSプロジェクトには、SQLite形式で約160MBのCoreData永続ストアが付属しています。そこにはたくさんのグループ化された情報があり、ユーザーはその中でお気に入りにマークを付けることができるはずです。このためには、データベース(の少なくとも一部)に書き込み機能が必要です。しかしもちろん、アプリケーションバンドルで出荷される永続ストアは設計上読み取り専用です。

ストアに読み取り/書き込み機能を持たせたい場合は、ストアをコピーする必要があります。アプリのドキュメントフォルダー。とにかく、そのデータベースの主要部分は読み取り専用であるのに対し、アプリは2倍のサイズになるため、これは行いたくありません。それはリソースの無駄になります。

NSPersistentStoreCoordinatorの複数の永続ストア

これが、2つの永続ストアを使用することを考えた理由です。 1つ目はバンドル内の大きなもので、2つ目はドキュメントフォルダー内の小さなもので、大きなストアとの関係を持つ特別な「お気に入り」エンティティを格納します。

私はこの点で何かが可能であることを知っていますが、詳細を見つけることができません。複数のオブジェクトモデルもある場合、複数のストアのみを使用する必要がありますか? 1つのオブジェクトモデルを2つの永続ストアに「分散」させることはできますか? Core Data Programming docs を参照すると、これを設定する方法についての実際のリファレンスが見つかりません。また、マーカス・サラの本はこのトピックを掘り下げていないようです:

NSPersistentStoreCoordinatorに複数のNSPersistentStoreを追加することができます。これは、複数のファイルに分割されたデータを処理するときに役立ちます。ただし、この例では、1つのファイルがあります。 ( Marcus Zarra:「コアデータ-Mac OS Xでデータを永続化するためのAppleのAPI」71ページ

質問

私が考えていることがCoreDataと複数の永続ストアで可能かどうかを誰が教えてくれますか?そして、これを達成する方法についてのヒントを提供できますか?トピックを扱うオンライン/オフラインのリソースも非常に高く評価されています。

41
epologee

答えはイエスです。 @Calebは適切なリソースを指していますが、それを機能させるのはまだかなり厄介です。私はここに履歴書を置くと思いました:

2つのNSPersistentStoreインスタンスが同じモデルを共有するには、エンティティの文字列名のサブセットである構成をモデルに追加する必要があります。

Model configurations

モデルでは、2番目のストアに属するエンティティに、フェッチされたプロパティ(googlabilityの場合はNSFetchedPropertyDescription)を追加します。これは非常に単純なストアドプロシージャであり、次のようになります。

NSPredicate format for the fetched property

次に、永続ストアコーディネーターにストアを追加するときに、configuration引数の文字列を使用します(詳細 オプションに関する情報はこちら ):

[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                          configuration:@"ModifyInBackground" 
                                                    URL:storeURL1
                                                options:options
                                                  error:&error]

[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                          configuration:@"ModifyInMain"
                                                    URL:storeURL2 
                                                options:options 
                                                  error:&error]

最後に、ストアBのエンティティからストアAのエンティティに移動する場合は、フェッチされたプロパティにアクセスするだけで、障害をトリガーするのと同じようにトリガーします。

注:リンクを確立するために作成する述語は複数の結果をもたらす可能性があるため、フェッチされたプロパティは常にNSArrayを返します。 1つのエンティティだけにアクセスしたい場合は、次のようなものをNSManagedObjectサブクラスのラッパーメソッドに配置できます。

Wallpaper *recordedWallpaper = [record.wallpaper lastObject];
46
epologee

はい、1つのモデルに複数のストアを使用できますが、異なるストア内のオブジェクト間に関係を作成することはできません。 Core Dataプログラミングガイドの Cross Store Relationships セクションを探してください。これは基本的にそれを示しており、あるストアのオブジェクトを別のストアのオブジェクトに関連付ける必要がある場合は、フェッチされたプロパティの使用を推奨しています。

5
Caleb

1つの考え:異なるストアをまとめて作成し、ストアごとに異なる永続的なストアコーディネーターを作成することもできます。次に、モデルパーツごとに異なる管理対象オブジェクトコンテキストを作成します。つまり、私には、学生、大学、コースの3つのエンティティを持つモデルがあるとしましょう。 Studentエンティティと大学エンティティをstore1に格納し、CourseをStore2に格納するとします。2セットのmanagedObjectContext、ペシステントストア、および永続コーディネーターがあります。ストア間の関係を設定できないことを考えると、あるコンテキストでの変更が別のコンテキストに影響を与えることはありません。別のモデルを作成したり、それらをストアなどに関連付けたりする必要はありません。

1
Shripada