1

タイトルが示唆しているように、さまざまなバックグラウンドスレッドのオブジェクトでいっぱいになるコアデータアプリケーションを使用しています(XML解析)

私のバックグラウンドスレッドでは、これを行っています

managedContext = [[NSManagedObjectContext alloc] init];
[managedContext setUndoManager:nil];

[managedContext setPersistentStoreCoordinator: [[DataManager sharedManager] persistentStoreCoordinator]];

 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
 [nc addObserver:self
        selector:@selector(mergeChanges:)
            name:NSManagedObjectContextDidSaveNotification
          object:managedContext];


NSMutableArray *returnSource = [[self parseDocument:doc] retain];


 [managedContext save:&error];

 if (error) {
     NSLog(@"saving error in datafeed"); 
 }

 [managedContext reset];

[self performSelectorOnMainThread:@selector(parseCompleteWithSource:) withObject:returnSource waitUntilDone:YES];

Mergeメソッドは次のようになります。

NSManagedObjectContext *mainContext = [[DataManager sharedManager] managedObjectContext];

// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                              withObject:notification
                           waitUntilDone:YES];  

[[NSNotificationCenter defaultCenter] removeObserver:self];

マージは成功したと思いますが、UITableViewに表示したいので、オブジェクトが無効になっていることを常に通知します。

[managedContext reset];

私がやりたいのは、現在データベースにあるアイテムを表示し、バックグラウンドでxmlを解析し、それが終了したら、UITableViewを新しい/更新されたオブジェクトで更新したいです。どうすればよいですか、オブジェクトを他のコンテキストに「更新」できますか、それともマージが正しく機能しませんか?

Main ObjectContextで特定の何かを定義する必要がありますか?運が悪かったので、さまざまなマージポリシーを試しました。

あなたが私を助けてくれることを願っています、ありがとう!

4

2 に答える 2

3

あなたの問題はreturnSource配列の内容だと思います。それがインスタンスの束であるNSManagedObject場合、それらはバックグラウンド スレッド コンテキストによってバックグラウンド スレッドで作成されます。

を呼び出すと-[NSManagedObjectContext reset]、それらが無効になります。これは、コンテキストに明示的に指示することだからです。しかし、それは大きな問題ではありません。

次に、配列をメインスレッドに送信し、NSManagedObjectスレッドの境界を越えてインスタンスを渡します。コンテキスト間では、大きな問題が発生します。

あなたがする必要があるのは:

  1. NSManagedObjectIDので配列を作成しますNSManagedObject
  2. スレッド境界を越えてオブジェクト ID 配列を送信します。
  3. NSManagedObjectそのコンテキストを使用して、新しいスレッドの管理対象オブジェクト ID から s を使用して配列を再作成します。

3 つのルール(3 回目に何かを書くときは、それを一般的なものにする)に従って、Core Data ヘルパーをいくつか作成しました。

最も重要なことは、スレッドごとに異なる管理対象オブジェクト コンテキストを管理し、通知を処理し、すべての迷惑メールを処理するという複雑さを隠したことです。代わりに、スレッド ローカル コンテキストの概念を導入しました。NSManagedObjectContext現在のスレッドが終了したときに更新とクリーンアップのために自動的に登録する、基本的に遅延作成されたインスタンス。

通常の使用例:

NSManagedObjectCotext* context = [NSManagedObjectCotext threadLocalContext];
// Do your stuff!!
NSError* error = nil;
if (![context saveWithFailureOption:NSManagedObjectContextCWSaveFailureOptionThreadDefault 
                              error:&error]) 
{
    // Handle error.
}

Apple.com からのニュース RSS を解析して Core Data に保存するためのサンプル アプリを含む完全なソース コードは、https ://github.com/jayway/CWCoreData から入手できます。

于 2011-07-26T18:21:55.150 に答える
1

この場合reset、バックグラウンド コンテキストを呼び出す理由はありません。これは、バックグラウンド スレッドでいずれにせよ消えてしまい、どのような場合でも再度使用することはないためです。resetコンテキストに前のステップを忘れさせたい場合は、通常、元に戻す管理を使用します。

ここでの主な問題は、バックグラウンド スレッドが、作成した管理オブジェクト コンテキストから通知を受け取るように構成されていることです。それはかなり無意味です。

NSManagedObjectContextDidSaveNotification代わりに、テーブルビュー コントローラーを (フロント スレッドで) 登録して、バックグラウンド スレッドでコンテキストからを受け取る必要があります。そうすれば、バックグラウンド コンテキストが保存されると、フロント/メイン コンテキストが新しいデータで更新され、テーブルビューの更新がトリガーされます。

于 2011-07-26T16:09:28.913 に答える