0

私は単に解決策を理解できない問題を抱えています。

Core Data (xCode によって作成された AppDelegate の templatecode を使用) を使用するように構成されたアプリは、バックグラウンド スレッドで大量のデータをインポートします。問題は、大規模なインポートを実行した場合、UI スレッドで Core Data に加えたすべての変更が (時々) ストアに保存されないことです。インポートを実行しない場合、すべてのデータは正しく保存され、問題は一貫していません。これはオン/オフの問題ですが、問題の原因となっているインポートであることが判明しました。

私のスレッドコードは次のようになります(簡略化)

-(void)startSynchronization{
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(startSync:) object:nil];
[self.thread start];
}


-(void)startSync{
NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] init];  
[importContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
[importContext setUndoManager:nil];
... import a lot of code and create thousands of core data entities..

}

persistentStoreCoordinator (PSC 以降) は、アプリの AppDelegate からの PSC であり、これが問題だと思います。複数のスレッドが個別の PSC を使用する必要があることを読みましたが、PSC を作成し、AppDelegate テンプレート コードで作成されたコア データ ファイルに割り当てるにはどうすればよいですか?

インポート後の Core Data の読み取りは正常に機能していますが、後で Core Data モデルの「ドキュメント」エンティティの 1 つをお気に入りとしてタグ付けすると、save on を呼び出しても、この変更はデータベースに書き込まれません。 AppDelegate からの私のコンテキスト。

グローバル PSC は、複数のコンテキスト、アプリ内の 1 つのコンテキスト、およびスレッド インポート コード内のインポート コンテキストを同期するために使用されていると思いましたか?

インポート コードと UI コードが同じ変更を認識し、ストアが一貫していることを確認するにはどうすればよいですか?

ありがとうございました

/ジェイコブ

4

1 に答える 1

3

彼らは、iOS 5/MacOS 10.7 でマルチスレッドが機能する方法を刷新しました。Core Data のマルチスレッド化には、 、 、 の 3 つのモードがNSConfinementConcurrencyTypeありNSPrivateQueueConcurrencyTypeますNSMainQueueConcurrencyType。最初のものは過去のやり方で、あなたが使っているものです。他のものについて言及するのは、調べる価値があるかもしれないし、用語が検索の際に役立つかもしれないからです。

スレッド制限方式の場合は、現在行っているように、スレッドごとに新しい管理対象オブジェクト コンテキストを作成します。saveループの後、バックグラウンド コンテキストで呼び出していると思います。不足しているステップは、に応答していNSManagedObjectContextDidSaveNotificationます。Appleのドキュメントから:

通常、スレッド A では、管理オブジェクト コンテキストの保存通知に登録しますNSManagedObjectContextDidSaveNotification。通知を受け取ると、そのユーザー情報ディクショナリには、スレッド B で挿入、削除、および更新された管理対象オブジェクトの配列が含まれています。ただし、管理対象オブジェクトは別のスレッドに関連付けられているため、それらに直接アクセスしないでください。mergeChangesFromContextDidSaveNotification:代わりに、 (スレッド A のコンテキストに送信する) に引数として通知を渡します。このメソッドを使用すると、コンテキストは変更を安全にマージできます。

要約すると、その通知をサブスクライブし、それが発生したとき (およびセレクターが呼び出されたとき)mergeChangesFromContextDidSaveNotification:に、メイン スレッドのマネージド オブジェクト コンテキストを呼び出して、通知オブジェクトを後者のメソッドに渡します。

- (void)mergeChanges:(NSNotification *)notification 
{
    if (notification.object != self.context) {
        [self.context mergeChangesFromContextDidSaveNotification:notification];
    }

    return;
}

既に通知をサブスクライブしており、それがself.contextメイン スレッドのマネージド オブジェクト コンテキストを参照しているとします。これにより、更新の取得が処理されるはずです。

上記で他の同時実行の種類について言及した理由は、(最新の OS を使用している場合) 同時実行を実行する別の方法に、親コンテキストと子コンテキストが関係しているためです。プライベート キュー モードで動作するコンテキストを持ち、その親をメイン MOC に設定できます。コンテキストに親がある場合、子コンテキストでの保存操作は、ディスクに触れることなく、その変更を親にプッシュするだけです。これは、検討できる別のパターンである可能性があります。

于 2012-05-30T08:06:46.243 に答える