最近我开了一个只需要一个商店的新应用程序(没有基于文档的应用程序)。有一段时间我很高兴认为我最终可以摆脱围绕NSManagedObjectContext ...直到我想在后台保存: - (
现在我对自己的代码感到困惑。例如:
- (void)awakeFromInsert
{
[super awakeFromInsert];
[self resetCard];
self.creationDate = TODAY;
self.dictionary = [Dictionary activeDictionary];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:NOTE_NEWCARD object:self];
}
[activeactiveDictionary]是一个NSManagedObject静态函数,返回指向主线程中创建的NSManagedObject的指针。这将在后台保存期间导致交叉/上下文错误。因为我的程序总是从同一个商店读取,我以为我可以避免写这个:
[Dictionary activeDictionaryWithContext:...]
我认为使用MagicalRecord,只要我总是使用相同的后端工作就可以避免传递上下文指针。我应该使用哪个函数来获取该上下文?
[NSManagedObjectContext MR_defaultContext]
[NSManagedObjectContext MR_context]
[NSManagedObjectContext MR_contextForCurrentThread]
在示例中,对象在通知中发送自身,这几乎被授予导致更多冲突的内容。
在我看来,我的对象只有在主要上下文中运行时才会发出副作用操作/通知。但是,其中一些边操作会更改我的对象图,从而创建其他实体的新实例。
如果我用[MagicalRecord MR_saveAll]保存,我可以安全地省略我提到的两个有问题的函数调用吗?
我是否应该假设新后台保存上下文的对象是我主线程中的对象的精确副本而不调用那些额外的函数?
现在我遇到了问题,因为我从没想过awakeFromInsert会为同一个商店的同一个对象多次运行。我在考虑这样的事情:
- (void)awakeFromInsert
{
[super awakeFromInsert];
if ([self managedObjectContext] == [NSManagedObjectContext MR_defaultContext]) {
[self resetCard];
self.creationDate = TODAY;
self.dictionary = [Dictionary activeDictionary];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:NOTE_NEWCARD object:self];
}
}
这应该使我的awakeFromInsert代码只运行一次,但不能在后台保存上下文中运行。如果我这样做,我担心会丢失信息
答案 0 :(得分:1)
虽然您可以通过这种方式发送通知,但我建议反对。请记住,即使CoreData中有新的父子上下文,NSManagedObjects也是 NOT 线程安全。如果您创建或导入对象,则需要在将它们用于其他上下文之前保存它们。
MagicalRecord为后台保存提供了一个相对简单的API:
[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext){
MyEntity *newEntity = [MyEntity MR_createInContext:localContext];
//perform other entity operations here
}];
此块可以为您完成所有工作,而无需担心正确设置NSManagedObjectContext。
您不应该在通知中传递NSManagedObjects的另一个原因是您不知道将收到通知的线程。这可能会导致崩溃,因为NSManagedObjects再次 NOT 线程安全。
您提供的通知方法的另一种替代方法是向 NSManagedObjectContextDidSaveNotification 添加观察者,并合并您对该通知的更改。这将仅在您保存对象后触发,并且通过父子关系或持久存储(旧方式)跨越上下文是安全的。