UITableView
iOS 5に、XMLからデータをダウンロードし、テーブルビューコントローラーを使用してそれらを表示するカタログアプリケーションがありますNSFetchedResultsController
。データはCoreDataに保存されますUIManagedDocument
。データのダウンロードとインポート時にメインキューをブロックしたくないため、データをダウンロードするためのバックグラウンドキューと、親としてデータをインポートするための新しい子NSManagedObjectContext
を作成しました。データのインポートが完了すると、子コンテキストで変更が行われ、変更が親コンテキストに伝播されます。カタログを閲覧するとき、必要に応じて追加のデータをインポートします。が自動保存されるまで、すべてが正常に機能しています。NSPrivateQueueConcurrencyType
document.managedObjectContext
-save:
UIManagedDocument
-com.apple.CoreData.SQLDebug 1
ドキュメントが自動保存されるタイミングを確認するために、コアデータのSQLデバッグをオンにしました。
重複するIDを持つドキュメントの自動保存オブジェクトが作成された後document.managedObjectContext
(すべてのエンティティIDデータベースには一意のIDパラメーターがあります)。
私は何が間違っているのですか?
問題を再現するための簡単なサンプルコードを作成しました。
コードは次のとおりです。http: //dl.dropbox.com/u/20987346/ViewController.m
完全なXcodeプロジェクトは次のとおりです。http://dl.dropbox.com/u/20987346/CoreDataTest.zip
以下は、バックグラウンドでインポートを実行しているメソッドです。
- (void)backgroundImport
{
static int counter;
NSManagedObjectContext *backgroundContext;
backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parentContext = self.document.managedObjectContext;
[backgroundContext performBlock:^{
NSManagedObject *entity;
for (int i = 0; i < 2; i++) {
entity = [self entityWithID:[NSNumber numberWithInt:arc4random() % 20 + 1]
inManagedObjectContext:backgroundContext];
[entity setValue:[NSString stringWithFormat:@"A Name %d", ++counter] forKey:@"name"];
}
[self dumpEntitiesInManagedObjectContext:backgroundContext];
NSError *error;
[backgroundContext save:&error];
if (error) NSLog(@"%@ (%@)", [error localizedDescription], [error localizedFailureReason]);
[backgroundContext.parentContext performBlock:^{
[self dumpEntitiesInManagedObjectContext:backgroundContext.parentContext];
}];
}];
}
このメソッドは2つのエンティティをインポートします。-entityWithID:
指定されたID属性を持つエンティティをフェッチし、存在しない場合は、を使用してエンティティを作成しますNSEntityDescription -insertNewObjectForEntityForName:
。ログに記録するすべての-dumpEntitiesInManagedObjectContext:
エンティティをダンプします(インポートコンテキストで1回、ドキュメントのコンテキストで1回)。
問題は、ドキュメントが自動保存され、追加のインポートが行われると、ログに次のように表示されることです。
[1140b] Entities: 10 [fb03] Entities: 11
[1140b] 2: A Name 1 [fb03] 2: A Name 1
[1140b] 3: A Name 4 [fb03] 3: A Name 4
[1140b] 4: A Name 8 [fb03] 4: A Name 8
[1140b] 5: A Name 12 [fb03] 5: A Name 12
[1140b] 6: A Name 10 [fb03] 6: A Name 10
[1140b] 8: A Name 6 [fb03] 8: A Name 6
[1140b] **12: A Name 11** [fb03] **12: A Name 11**
[1140b] 13: A Name 9 [fb03] **12: A Name 5**
[1140b] 17: A Name 3 [fb03] 13: A Name 9
[1140b] 18: A Name 2 [fb03] 17: A Name 3
[fb03] 18: A Name 2
インポートコンテキストには10個のエンティティがありますが、メインコンテキストには11個のエンティティがあり、ID12のエンティティは重複しています。古いオブジェクトは親コンテキストで変更されていないようですが、代わりに追加されています。