我在 iOS 5 中有一个目录应用程序,它从 XML 下载数据并UITableView
使用带有NSFetchedResultsController
. 数据存储在 Core Data 中UIManagedDocument
。因为我不想在下载和导入数据时阻塞主队列,所以我创建了一个用于下载数据的后台队列和一个新的子队列,NSManagedObjectContext
用于作为父NSPrivateQueueConcurrencyType
级导入数据。document.managedObjectContext
当我完成导入数据时,我-save:
在子上下文中进行了更改,并且更改会传播到父上下文。浏览目录时,我会在需要时导入其他数据。一切正常,直到UIManagedDocument
自动保存。
我已打开核心数据 SQL 调试,-com.apple.CoreData.SQLDebug 1
以查看文档何时自动保存。
在创建具有重复 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];
}];
}];
}
该方法导入两个实体。获取具有指定 ID 属性的-entityWithID:
实体,如果它不存在,则使用NSEntityDescription -insertNewObjectForEntityForName:
. 转储所有实体以-dumpEntitiesInManagedObjectContext:
记录(一次在导入上下文中,一次在文档上下文中)。
问题是当文档被自动保存并完成一些额外的导入时,我在日志中得到以下内容:
[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 个实体,ID 为 12 的实体是重复的。似乎旧对象没有在父上下文中修改,而是添加了。