5

問題文

同じ PersistentStoreCoordinator に割り当てられた 2 つの SQLite ストアの 1 つである読み取り/書き込みストアにレコードを保存しようとすると、iPhone アプリがクラッシュします。レコードを保存する際の明らかな問題の 1 つは、PersistentStoreCoordinator がデータを保存するストアを認識していないことです (これを実現する方法がわからないためです)。

まず、全体像を示して、私のアプローチが適切であることを確認します。次に、実装の詳細を提供します。

バックグラウンド

これは、私が取り組んでいる実際のアプリの重要な側面を表す簡単な例です。

マネージド オブジェクト モデル

シードデータ

シードデータ

ユーザー入力シナリオ

ユーザー入力シナリオ

現在の実装

コアデータの実装

コアデータの実装

データの保存と検索

データの保存と検索

もちろん、選択リストを参照して属性を選択するときに、その選択が 2 つの異なるストアからのものであるという証拠をユーザーに与えるべきではありません。

永続ストア コーディネーターのセットアップ

- (NSPersistentStoreCoordinator*)persistentStoreCoordinator {
   if (_persistentStoreCoordinator == nil) {
       NSArray *bundles = @[[NSBundle bundleForClass:[self class]]];
       _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:bundles]];

       NSError *error;
       //--------------------------------------------------
       // Set options for the USER DATA Persistent Store.
       NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
                                       NSInferMappingModelAutomaticallyOption : @YES};
       //--------------------------------------------------
       // Add the USER DATA Store to the Persistent Store Coordinator.
       NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                                   configuration:nil
                                                                                             URL:self.persistentStorePathForUserData
                                                                                         options:options
                                                                                           error:&error];
       //--------------------------------------------------
       // Set options for the SEED DATA Persistent Store.
       options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
                         NSInferMappingModelAutomaticallyOption : @YES,
                                NSReadOnlyPersistentStoreOption : @YES};
       //--------------------------------------------------
       // Add the SEED DATA Store to the Persistent Store Coordinator.
       persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                configuration:nil
                                                                          URL:self.persistentStorePathForSeedData
                                                                      options:options
                                                                        error:&error];
   }
   return _persistentStoreCoordinator;
}

重要な目標

次の点に注意してください。

  1. 可能であれば、舞台裏でデータのバージョンを管理する必要なしにシード データの更新を行うことを希望します (つまり、新しいまたは変更されたシード データ レコードのみをアプリの更新で提供し、何らかの方法で削除を処理する)、バージョン チェック機能を実装する必要があります。ユーザーがバージョン n から n+5 にアップグレードする状況を処理するコード。
  2. ユーザー データとシード データには、2 つの間で重複するレコードを含めてはならず、同じ ManagedObjectModel を使用する必要があります。したがって、データとモデルの観点から、2 つのストアをマージしたり、1 つのストアを別のストアに移行したりする必要はありません。

リサーチ

この場合、 複数のストアから単一の永続ストアにオブジェクトを保存すると、2 つのストアがマージされ、すべてのレコードがフェッチされ、重複が除外され、コンテキストが保存されます。何千ものレコードをマージして重複をチェックする必要がないことを望んでいます。(上記の重要な目標 #2 を参照してください。)

この場合、 2 つの iOS Core Data Persistent Store をマージする効率的な方法は何ですか? 、特定のエンティティは読み取り専用で、その他は読み取り/書き込み可能です。私のアプリでは、シード データ ストア内のすべてのエンティティは読み取り専用であり、ユーザー データ ストア内の同じエンティティは読み取り/書き込みです。したがって、移行は適用できないと思います。(上記の重要な目標 #2 を参照してください。)

Apple のCore Data Programming Guideの「Persistent Store Coordinator」の下にある図 4「高度な永続化スタック」は、2 つの Store を使用する Core Data の実装を示していますが、ここでも、各 Store は個別の異なるオブジェクトで構成されています。私のアプリでは、各オブジェクトが各 Store に表示されます。

ここで提案されている解決策 Combining Two SQLite Stores Into Oneは、異なるストア内のオブジェクト間に関係のない 2 つのストアを持つことに関連しているように見えますが、私が実装したものと比較するための詳細は提供されていません。

私はMarcus Zarra による Core Data (2nd Edition)の最初の 3 つの章を読みましたが、彼は移行を必要としない 2 つのストアの使用には取り掛かりませんでした。ただし、第 3 章では、バージョン管理の非常に明確な例を示しています。(複雑なので、上記の重要な目標 #1 にたどり着きました。)

このソリューション ( Which persistent store is used by default by core data in iPhone ) は、ManagedObjectModel の複数の構成を使用することを提案していますが、各エンティティは 1 つの構成にのみ割り当てられます。この解決策が私の状況にどのように推定できるか、あるいは推定できるかどうかさえわかりません。

ここで提案されている解決策は、2 種類の永続ストアを持つ NSPersistentStoreCoordinator でしょうか。、私が必要とするものに近いです。残念ながら、リクエストのみが処理されます。保存用のクラス NSManagedObjectContext に、NSFetchRequest メソッド setAffectedStores に類似したメソッドがありません。

4

2 に答える 2

2

Ray WenderlichがMic Pringleを紹介してくれたおかげで、Mic はマネージド オブジェクト モデル アーキテクチャを提案してくれました。このアーキテクチャによって、私は自分の目標を守りながら問題を解決することができました。解決策の鍵は、抽象エンティティをユーザーおよびシード エンティティの親エンティティとして利用することです。

マネージド オブジェクト モデル

このアーキテクチャでは、別々のストアに割り当てられる 2 つの構成を作成できます。1) UserData - ユーザーのドキュメント ディレクトリにある r/w ストア。

ユーザーデータ構成

2) SeedData - App Bundle にある r のみのストア。

シードデータ構成

欠点は、シード データ エンティティのレコード ID を維持する必要があることです (構成間の関係が許可されていないため)。しかし、大きな利点は、ユーザーのエントリに影響を与えずにシード データを変更または追加できることです。この質問の元の投稿の研究セクションで説明されている面倒なソリューションのいずれか。

于 2014-08-21T20:19:57.570 に答える
1

1 つのコンテキスト/コーディネーターと 2 つのストアを使用してデータを保存するという中心的な問題については、次のアプローチが必要です。

  1. を介してユーザーが編集可能なストアを追加する場合、返されるオブジェクトaddPersistentStoreへの参照を保存します。NSPersistentStore
  2. ユーザーが編集可能なストアに保存する新しいオブジェクトを作成するときは、次のようにします。

    NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:@"Vehicle" inManagedObjectContext:self.managedObjectContext];
    [self.managedObjectContext assignObject:newObject toPersistentStore:userEditableStore];
    

    ここで重要なのは、変更を保存するassignObject:toPersistentStore: 前に明示的に呼び出すことです。

関連する質問:

可能であれば、舞台裏でデータのバージョンを管理することなく、シード データの更新を行うことをお勧めします...

編集不可のストアをアプリ バンドルに残す場合 (つまり、ファイルを別の場所にコピーしない場合)、アプリの新しいバージョンに新しいバージョンのデータを含めることができます。App Bundle に含まれているバージョンを常に使用するため、最新のデータを入手できます。

シード ストアからユーザー ストアにデータをコピーすることになった場合は、各エントリに追加時のアプリ (またはシード ストア) のバージョン番号が含まれていることを確認してください。これにより、重複を簡単に回避できます。

ユーザー データとシード データには、2 つの間で重複するレコードを含めてはならず、同じ ManagedObjectModel を使用する必要があります。したがって、データとモデルの観点から、2 つのストアをマージしたり、1 つのストアを別のストアに移行したりする必要はありません。

異なるストア内のオブジェクト間に関係がない場合は、あるデータから別のデータにデータをコピーする必要はありません。これはコア データでは許可されていないためです。リレーションシップが必要な場合 (そのように聞こえます)、fetched propertiesを調べてください。これらは、エンティティ タイプの属性または関係によく似ていますが、内部的には永続ストアから値を検索します。複数の永続ストア ファイルを使用すると、異なるストア内のオブジェクト間の関係とほとんど同じではありませんが、これが可能になります。

于 2014-05-14T23:09:12.577 に答える