简体   繁体   English

保存NSManagedObjectContext这个'干净'时为什么会出现合并错误?

[英]Why am I getting a merge error when saving an NSManagedObjectContext this 'clean'?

thanks in advance for any help. 提前感谢您的帮助。 I've spent today battling this and I think that there is something seriously wrong with my understanding of how the framework works. 我今天花了很多时间与此作斗争,我认为我对框架的运作方式有一些严重的错误。

I'm working on a core data application where the entities have a parent/child relationship. 我正在开发一个核心数据应用程序,其中实体具有父/子关系。 The application creates an NSManagedObjectContext (MOC) on startup. 应用程序在启动时创建NSManagedObjectContext(MOC)。 When the application is run for the first time it uses an async block to import the contents of a plist into a second MOC (the root node is obtained from the main MOC using the URI and -managedObjectIDForURIRepresentation:), just before the block finishes it saves the second context. 当应用程序第一次运行时,它使用异步块将plist的内容导入第二个MOC(根节点是使用URI和-managedObjectIDForURIRepresentation :)从主MOC获取的,就在块完成之前保存第二个上下文。

In my data controller I subscribe to NSManagedObjectContextDidSaveNotification and the following code is run when the notification is sent: 在我的数据控制器中,我订阅了NSManagedObjectContextDidSaveNotification,并在发送通知时运行以下代码:

- (void)backgroundContextDidSave:(NSNotification *)notification {
    if(![notification.object isEqual:self.managedObjectContext]){
        if (![NSThread isMainThread]) {
            [self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
                                   withObject:notification
                                waitUntilDone:NO];
            return;
    }       
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];        ;
    }
}

I've done a sanity check on this code and sure enough, when the second MOC saves, this is called from the thread executing the block, it is then deferred, and run from the main thread. 我已经对这段代码进行了完整性检查,当然,当第二个MOC保存时,从执行块的线程调用它,然后延迟,并从主线程运行。 The notification object contains all objects imported in the second MOC, including the two we're going to be dealing with next. 通知对象包含在第二个MOC中导入的所有对象,包括我们接下来要处理的两个对象。

When this has finished I run the following code which is in a method of the NSManagedObject subclass the objects belong to, it is simply meant to remove a child from its parent: 完成后,我运行以下代码,该代码位于对象所属的NSManagedObject子类的方法中,它只是意味着从子父中删除子代:

TreeEntry *oldParent=self.parent; //keep a pointer to the old parent around so we can delete self from the children

// These next four lines are a sanity check to make sure that both objects are on the same MOC we're saving
NSManagedObjectContext *selfContext=self.managedObjectContext;
NSManagedObjectContext *parentContext=self.parent.managedObjectContext;
NSManagedObjectContext *sharedContext=[[DataController sharedDataController] managedObjectContext];
assert([selfContext isEqual:parentContext] && [selfContext isEqual:sharedContext]);

// now we fault the two objects to make sure we can not possibly have them or any changes 
// to them in the state of the main MOC, by this time the second MOC is long gone
[sharedContext refreshObject:self.parent mergeChanges:NO];
[sharedContext refreshObject:self mergeChanges:NO]; 

// up to this point, sharedContex.insertedObjects, sharedContext.updatedObects and sharedContext.deletedObjects
// have all contained no objects at all. None of the above was necessary as the MOC held no changes at all
[sharedContext saveChanges]; // we save it to, well, just to make sure I guess, I may be going crazy

// Now we carry out two changes to the objects, problem occurs if only one change is carried out,
// I'm showing both to show that there relationship is being kept consistent and valid
self.parent=nil;
[oldParent removeChild:self];


// When the next line is run the save fails with a merge conflict
[sharedContext saveChanges];

The last save fails with a Cocoa error 133020, which is a merge fail. 最后一次保存失败,出现Cocoa错误133020,这是合并失败。 The two NSMergeConflicts in the error relate to the entries we're dealing with (self and self.parent). 错误中的两个NSMergeConflicts与我们正在处理的条目(self和self.parent)有关。

I just don't understand how that can be. 我只是不明白这是怎么回事。 The objects have no state when they are modified so they MUST be getting loaded from the store. 对象在被修改时没有状态,因此它们必须从商店加载。 Two simple changes are made and then when they are saved straight afterwards a merge conflict occurs. 进行两个简单的更改,然后在直接保存它们之后发生合并冲突。 How can that be? 怎么可能? nothing else has messed with the store and we've just loaded the objects from it. 没有别的东西搞砸了商店,我们只是加载了它的对象。

I know I can change the merge policy but I don't want to do it without understanding what's going on. 我知道我可以更改合并政策,但我不想在不了解正在发生的情况下这样做。

Any ideas? 有任何想法吗? I'm sure it's just that my mental model if what's going on is wrong, but I've not been able to set it right all day! 我确信这只是我的心理模型,如果发生的事情是错的,但我一直都没能把它整理好!

Ok, it WAS a fundamental misunderstanding on my part of how the framework works, or to be more accurate, the NSManagedStoreCoordinator cache. 好吧,这是我对框架如何工作或更准确的NSManagedStoreCoordinator缓存的一个基本误解。

When I save the background context the changes go to disk, but apparently the NSManagedStoreCoordinator (which both contexts share) doesn't update or invalidate its cache. 当我保存后台上下文时,更改将转到磁盘,但显然NSManagedStoreCoordinator(两个上下文共享)不会更新或使其缓存无效。

When I refresh the objects in the main MOC the data used to re-populate them comes from the cache, which still has the old data. 当我刷新主MOC中的对象时,用于重新填充它们的数据来自缓存,缓存仍然具有旧数据。 It doesn't re-load from the disk. 它不会从磁盘重新加载。 The solution was to use [MOC setStalenessInterval:0.0] to force re-loading from disk. 解决方案是使用[MOC setStalenessInterval:0.0]强制从磁盘重新加载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我在这段代码中得到一个“未知类型名称NSManagedObjectContext”? - why am I getting an “unknown type name NSManagedObjectContext” in this code? 为什么在加载TableViewcontroller时出现此错误 - Why am I getting this error when loading my TableViewcontroller iPhone-当视图映射正确时,为什么会出现此错误? - iPhone - Why am I getting this error when the view mapping is correct? 声明NSManagedObjectContext时出错 - Error when declaring NSManagedObjectContext 为什么我会收到此 NSManaged Object 错误 - Why Am I Getting This NSManaged Object Error 为什么我会收到sqlite3error? - Why I am getting sqlite3error? 当我发送到许多请求时,为什么会出现此错误(HTTP错误400)? - Why i am getting this error (HTTP error 400.) when I send to many request? 当我从经度和纬度创建位置字符串时,为什么我在iOS中收到此链接器错误? - Why am I getting this linker error in iOS when I create location strings from longitude and latitude? 当我单击按钮时,为什么会出现“无法识别的选择器”错误? - Why am I getting a “unrecognized selector” error when I click on a button? 定义方法后,为什么会收到“无法识别的选择器发送到实例”错误? - Why am I getting an “unrecognised selector sent to instance” error when I have defined the method?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM