7

アプリに次の Core Data セットアップがあります。

Persistent Store Coordinator
  ^ Background MOC (NSPrivateQueueConcurrencyType)
      ^ Main Queue MOC (NSMainQueueConcurrencyType)

初期化コードは次のとおりです。

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundContext setPersistentStoreCoordinator:self.coordinator];
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setParentContext:_backgroundContext];

大量のデータをインポートするためにバックグラウンド MOC を使用しています。また、これを使用してバックグラウンドで複雑なフェッチ リクエストを実行し、オブジェクト ID をメイン キューに渡して、これらの ID を使用してオブジェクトをフェッチします。

これは非常にうまく機能します。ただし、バックグラウンド MOC で行われた変更をメイン キュー MOC に通知する方法がわかりません。メイン キューの MOC でフェッチ要求を実行すると、変更が取得されることはわかっていますが、それは私が望んでいることではありません。

NSManagedObjectContextObjectsDidChangeNotificationバックグラウンド MOC によってポストされた通知を使用しmergeChangesFromContextDidSaveNotification:て、メイン キュー MOC を呼び出しても問題ありませんか? これNSManagedObjectContextObjectsDidChangeNotificationにより、メイン キューの MOC の通知が発生します。ビューコントローラーでこの通知をリッスンし、変更を調べて、userInfoそれに応じてデータを再表示します。2 つの MOC が接続された 1 つの永続ストア コーディネーターがある場合、通常はこの方法で行うと思います。しかし、子/親のコンテキストがある場合、それが正しい方法であるかどうかはわかりません。

4

2 に答える 2

6

メイン MOC が非同期 I/O にプライベートな親 MOC を使用することは問題ありません。ただし、メイン MOC に代わってバックグラウンド作業を実行する以外の目的でその親 MOC を使用しないでください。これには多くの理由があります (その中には、一時的なオブジェクト ID に関連するパフォーマンスと厄介な問題があります)。

ストアのバックグラウンド更新を行いたい場合は、次のことをお勧めします。

PSC <--+-- PrivateMOC <---- MainMOC
       |
       +-- BackgroundPrivateMOC

これにより、PSC キャッシュを共有しながら、メイン MOC への中断を最小限に抑えるバックグラウンド操作が可能になります。

さて、データを共有するには...

MainMOC は、BackgroundPrivateMO からの DidSave 通知をリッスンしてマージする必要があります。

BackgroundMOC は、PrivateMOC からの DidSave 通知をリッスンしてマージできます。

これにより、マージで永続的なオブジェクト ID のみを使用できるようになり、パフォーマンスが最適化されます。

于 2014-03-03T20:52:56.117 に答える
3

NSManagedObjectContextObjectsDidChangeNotification通知を聞くことはおそらく最善の解決策ではないと思います。

私がそれを行う方法とそれが機能する方法は次のとおりです。メインコンテキストの作成は次のとおりです。

_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_mainContext.persistentStoreCoordinator = _persistentStoreCoordinator;

バックグラウンド コンテキストの作成は次のとおりです。

_backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_backgroundContext.parentContext = self.mainContext;

現在、バックグラウンド コンテキストは、オブジェクトの書き込み (または読み取り) のみを目的としています (バックグラウンド スレッドにある場合があります)。メイン コンテキストは、メイン キューからの読み取り専用です。バックグラウンド コンテキストでの保存は次のようになります。

__block BOOL saved = [_backgroundContext save:error];
if (saved && _backgroundContext.parentContext) {
    [_backgroundContext.parentContext performBlockAndWait:^{
        saved = [self.parentContext save:error];
    }];
}

この save メソッドは、すべての変更がメイン コンテキストに反映されることを保証します。多くのバックグラウンド スレッドで多くの作業を行う場合は、performBlockAndWait:コンテキストでの相互排除を提供するメソッドに慣れてください。

オブジェクトの変更について通知を受けたい場合は、通知をリッスンする必要はありませんNSFetchedResultsController。デリゲートとしてセットアップして登録するだけです。

于 2013-10-18T15:18:01.987 に答える