我正在使用NSManagedObjectContextObjectsDidChangeNotification,我有一个问题,在插入一个对象然后调用rollback以便删除它之后,带有已删除对象的更改通知被调用两次。这个意外的通知引起了我追溯到这个问题的复杂性。我已编辑Apple's Earthquakes example来演示此问题。编辑是:
- (void)viewDidLoad {
[super viewDidLoad];
[self reloadTableView:self];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(contextObjectsDidChangeNotification:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:self.managedObjectContext];
AAPLQuake* quake = (AAPLQuake *)[NSEntityDescription insertNewObjectForEntityForName:@"Quake" inManagedObjectContext:self.managedObjectContext];
NSLog(@"Why is deleted notified twice?");
[self.managedObjectContext rollback];
}
-(void)contextObjectsDidChangeNotification:(NSNotification*)notify{
NSLog(@"contextObjectsDidChangeNotification:");
NSDictionary* userInfo = notify.userInfo;
NSSet* inserted = userInfo[NSInsertedObjectsKey];
if(inserted){
NSLog(@"\tinserted %ld", inserted.count);
}
NSSet* deleted = userInfo[NSDeletedObjectsKey];
if(deleted){
NSLog(@"\tdeleted %ld", deleted.count);
}
}
运行此结果会产生以下输出:
2015-12-23 00:15:20.086 Earthquakes[7631:5431685] Why is deleted called twice?
2015-12-23 00:15:20.086 Earthquakes[7631:5431685] contextObjectsDidChangeNotification:
2015-12-23 00:15:20.086 Earthquakes[7631:5431685] inserted 1
2015-12-23 00:15:20.086 Earthquakes[7631:5431685] contextObjectsDidChangeNotification:
2015-12-23 00:15:20.087 Earthquakes[7631:5431685] deleted 1
2015-12-23 00:15:20.087 Earthquakes[7631:5431685] contextObjectsDidChangeNotification:
2015-12-23 00:15:20.087 Earthquakes[7631:5431685] deleted 1
可用的示例项目here。
有谁知道为什么会这样?我在OS X 10.11.2和iOS 9.2上都遇到过它。
答案 0 :(得分:2)
我看到了同样的行为,我不知道它为什么会发生。但是,看起来您可以通过查看托管对象的hasChanges
属性来区分第一个调用与第二个调用。在第一次通话时,hasChanges
为YES,在第二次通话时,它为NO。这应该至少足以避免自己两次处理删除。
对象的deleted
属性发生了同样的变化,因此最好同时检查两者。
答案 1 :(得分:1)
rollback
调用processPendingChanges
,第一个通知是对象被删除的结果,并且似乎具有所需的所有其他值(inserted
和{{1都是真的。)
第二个通知是在deleted
的实施中第二次调用processPendingChanges
的结果。请注意,这次它甚至没有标记为rollback
。
起初,我认为可能是由于删除传播,但即使deleted
设置为NO,也会发生第二次通知。
以下跟踪只是propagatesDeletesAtEndOfEvent
方法(我删除了除rollback
以外的所有方法调用以保持简短 - 我还删除了对retain / release的调用。)
可能有充分的理由对NSManagedObjectContext
进行第二次调用,因为那里发生了相当多的工作(参见本文末尾)。
如果我不得不猜测,我会说回滚的实现存在一个错误,其中删除的对象没有从第二个通知的数据中删除。
我建议采取两种行动方案。首先,使用apple提交错误报告。其次,当您处理对象更改事件时,请检查已删除通知集中对象的processPendingChanges
属性,并忽略任何未标记为deleted
的对象。
这是跟踪......
deleted