gpt4 book ai didi

objective-c - 核心数据: How to merge inserts/updates/deletes between two NSManagedObjectContext's while maintaining the merge as an undoable step?

转载 作者:行者123 更新时间:2023-12-03 16:44:02 27 4
gpt4 key购买 nike

我有一个基于文档的 Core Data 应用程序(在 Mac OS X 10.5 及更高版本上运行),我尝试在主线程上使用两个 NSManagedObjectContext。我想将辅助上下文中所做的更改合并到我的主要(主要)上下文中。此外,我希望从辅助上下文合并的更改是不可撤销的,并导致文档被标记为“脏”。我想我的问题类似于“Undoing Core Data insertions that are performed off the main thread ”,但是,ATM,我没有使用不同的线程。

我一直在观察 NSManagedObjectContextDidSaveNotification (在调用 -[self.secondaryContext save:] 时从第二个上下文发送),如下所示:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mocDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:self.secondaryContext];

在观察者调用的 -mocDidSave: 方法中,我尝试在主上下文上使用 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] 将辅助上下文中的更改合并到主要背景:

- (void)mocDidSave:(NSNotification *)notification
{
[self.primaryContext mergeChangesFromContextDidSaveNotification:notification];
}

但是,虽然插入的对象很容易出现在我的数组 Controller 中,但文档并未标记为脏,并且新添加的托管对象的 isInserted 属性未设置为 YES。此外,插入(到主要上下文中)是不可撤消的。

对任何插入的对象进行重新故障至少会将文档标记为脏,但插入仍然不可撤消:

- (void)mocDidSave:(NSNotification *)notification
{
[self.primaryContext mergeChangesFromContextDidSaveNotification:notification];

for (NSManagedObject *insertedObject in [[notification userInfo] objectForKey:NSInsertedObjectsKey]) {
[self.primaryContext refreshObject:[self.primaryContext existingObjectWithID:[insertedObject objectID] error:NULL] mergeChanges:NO];
}
}

W.r.t。 -mocDidSave:,我使用自定义实现获得了稍微好一点的结果:

- (void)mocDidSave:(NSNotification *)notification
{
NSDictionary *userInfo = [notification userInfo];

NSSet *insertedObjects = [userInfo objectForKey:NSInsertedObjectsKey];
if ([insertedObjects count]) {
NSMutableArray *newObjects = [NSMutableArray array];
NSManagedObject *newObject = nil;
for (NSManagedObject *insertedObject in insertedObjects) {
newObject = [self.primaryContext existingObjectWithID:[insertedObject objectID] error:NULL];
if (newObject) {
[self.primaryContext insertObject:newObject];
[newObjects addObject:newObject];
}
}

[self.primaryContext processPendingChanges];

for (NSManagedObject *newObject in newObjects) {
[self.primaryContext refreshObject:newObject mergeChanges:NO];
}
}

NSSet *updatedObjects = [userInfo objectForKey:NSUpdatedObjectsKey];
if ([updatedObjects count]) {
NSManagedObject *staleObject = nil;
for (NSManagedObject *updatedObject in updatedObjects) {
staleObject = [self.primaryContext objectRegisteredForID:[updatedObject objectID]];
if (staleObject) {
[self.primaryContext refreshObject:staleObject mergeChanges:NO];
}
}
}

NSSet *deletedObjects = [userInfo objectForKey:NSDeletedObjectsKey];
if ([deletedObjects count]) {
NSManagedObject *staleObject = nil;
for (NSManagedObject *deletedObject in deletedObjects) {
staleObject = [self.primaryContext objectRegisteredForID:[deletedObject objectID]];
if (staleObject) {
[self.primaryContext deleteObject:staleObject];
}
}

[self.primaryContext processPendingChanges];
}
}

这会导致我的数组 Controller 更新,文档被标记为脏,并且插入和删除操作不可撤消。但是,我仍然遇到无法撤消的更新问题。我是否应该手动循环所有更新的对象并使用 -[NSManagedObjectchangedValues] 在主上下文中重新应用更改?

当然,这个自定义实现会在主上下文上重复辅助上下文中的大量工作。是否有任何其他/更好的方法可以在两个上下文之间进行合并,同时将合并保持为可撤消的步骤?

最佳答案

如果您没有使用单独的线程,那么您实际上不需要单独的上下文。在同一线程上使用两个上下文会增加复杂性,但不会带来任何好处。如果您不确定是否会使用线程,那么我强烈建议您仅使用一个上下文。过早的优化是万恶之源。

保存会重置撤消管理器,因此您无法使用 NSManagedObjectContextDidSaveNotification 来执行任何可以撤消的操作。正如您所发现的,您可以欺骗应用程序认为文档是脏的,但您不能强制撤消管理器记住上次保存的内容。

要获得无限制的撤消,唯一的方法是在幕后保存文档的多个版本。 IIRC,您还可以序列化撤消管理器,以便将其写入文件并重新加载以回溯。

关于objective-c - 核心数据: How to merge inserts/updates/deletes between two NSManagedObjectContext's while maintaining the merge as an undoable step?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6547950/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com