我们的表视图控制器使用NSFetchedResultsController
来显示Core Data中的数据。我们在后台下载新数据。当在新数据中修改实体时,在iOS 5.1.1手机上,我们看到将其视为表中的新行而不是更新。无法在iOS 5.1模拟器或iOS 6设备上复制。
UIApplicationDelegate
创建一个并发类型为NSManagedObjectContext
的{{1}}。我们的NSMainQueueConcurrencyType
实施UITableViewController
。在NSFetchedResultsControllerDelegate
中,我们将获取新数据。在获取数据的方法中,我们使用并发类型viewWillAppear
创建第二个NSManagedObjectContext
。我们在新的上下文上做NSPrivateQueueConcurrencyType
,并进行网络调用和json解析。有performBlock
来获取以前的数据,因此我们可以删除旧对象,或修改具有相同ID的任何现有实体。在修改现有实体或创建新实体之后,我们然后NSFetchRequest
旧实体对象。然后我们保存这个私有上下文。然后在父上下文中,执行deleteObject
以保存更改。
在iOS5.1上,表格不正确。如果我们更改对象而不是修改它,它将作为新行添加到表中。如果我们离开这个控制器并返回它,获取新数据,它会显示正确的数量。
AppDelegate.m
performBlock
从服务器获取的类
- (void)saveContext
{
[self.privateWriterContext performBlock:^{
NSError *error = nil;
[self.privateWriterContext save:&error];
// Handle error...
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.privateWriterContext];
}];
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)privateWriterContext
{
if (__privateWriterContext != nil) {
return __privateWriterContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__privateWriterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[__privateWriterContext setPersistentStoreCoordinator:coordinator];
}
return __privateWriterContext;
}
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[__managedObjectContext setParentContext:self.privateWriterContext];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(saveContext:)
name:NSManagedObjectContextDidSaveNotification
object:__managedObjectContext];
return __managedObjectContext;
}
答案 0 :(得分:1)
我最近也遇到了这个问题。
问题是由于不同线程中的两个上下文。
在运行iOS 5.1的设备上,合并它们会导致它插入新记录而不是更新它。我将后台线程更改为使用主上下文,问题就消失了。
不知道为什么合并在这种特殊情况下不起作用。
答案 1 :(得分:0)
我有样品问题。原因是awakeFromInsert的实现。当主队列上下文意外地合并私有队列时,将调用该方法。
我的代码就是这样。
public override func awakeFromInsert() {
super.awakeFromInsert()
let context = self.managedObjectContext!
let tag1 = NSEntityDescription.insertNewObjectForEntityForName("Tag", inManagedObjectContext: context) as! TagMO
tag1.name = "Dog"
let tag2 = NSEntityDescription.insertNewObjectForEntityForName("Tag", inManagedObjectContext: context) as! TagMO
tag2.name = "Cat"
tags = NSSet(array: [tag1, tag2])
}
在这种情况下,当从私有上下文合并到主队列上下文时,标记对象将是4而不是2。