CoreData NSUndoManager 关系问题
Posted
技术标签:
【中文标题】CoreData NSUndoManager 关系问题【英文标题】:CoreData NSUndoManager issues with relationships 【发布时间】:2015-09-13 19:09:39 【问题描述】:我有一个与 Department 具有多对一关系的托管对象 Employee。因此,一个员工可以在一个部门中,但部门可以包含多个员工。
我使用撤消管理器来注册某些员工的删除。之后我关闭撤消注册我删除了部门。部门删除会删除所有剩余的员工,因为它设置了Cascade Delete
规则。
NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext];
NSUndoManager *undoManager = [defaultContext undoManager];
[undoManager enableUndoRegistration];
[undoManager setActionName:@"Delete"];
[employee MR_deleteEntityInContext:defaultContext];
// let undo manager finish registering events on current run loop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
[undoManager disableUndoRegistration];
// ...
// somewhere later without undo manager enabled
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
Department *department = [departmentOnMainThread MR_inContext:localContext];
[department MR_deleteEntityInContext:localContext];
];
然后我撤消 Employee 的删除,它在我的上下文中与 Department 一起复活。
NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext];
NSUndoManager *undoManager = [defaultContext undoManager];
[undoManager enableUndoRegistration];
[undoManager undo];
[defaultContext MR_saveToPersistentStoreAndWait];
// let undo manager finish registering events on current run loop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]];
[undoManager disableUndoRegistration];
有趣的是,当我运行 undo 时,我的上下文的 [defaultContext deletedObjects]
包含 Department、我最初使用 NSUndoManager
捕获的 Employee 以及可能与 Department 一起被删除但实际上并未捕获更改的其他一些 Employee在删除原始员工期间。这个其他 Employee 的所有字段都设置为 nil。
出于好奇,我打电话给[defaultContext refreshAllObjects]
,回复如下:
CoreData:警告:NSManagedObjectContext 委托覆盖错误 处理行为以静默删除具有 ID 的对象 '0xd000000000280000 ' 和 用 nil/0 代替所有属性值,而不是抛出。
问题是,可能其他 Employee 应该真的被删除了,但是我怎样才能恢复原来的 Employee 和 Department 显然应该放回数据库?
NSUndoManager
将它们恢复为已删除的对象,这没有多大意义。
【问题讨论】:
请澄清:1. 从Department
实例到Employee
实例之间存在1:n 关系,而不是相反。 2. 员工的删除和该动作的撤消操作是自动注册的还是你有明确的代码?如果是这样,请发布代码。 3. 你先删除属于某个部门的员工,然后再删除还有员工的部门? 4. 您想先撤消第一个操作,然后再撤消第二个操作?
你运行的是什么版本的 Xcode?span>
@AminNegm-Awad 1. 正如我在一个部门很多员工之前所说的那样。 2. 我只注册第一次删除员工。从其他未启用撤消注册的控制器中删除的部门。 3. 我先删除了一个启用了撤消经理注册的员工,然后我删除了部门“账外”,然后我撤消了。 4. 我想撤消已删除的员工与部门,而不管整个部门后来与所有员工一起被删除。我希望部门在一个员工的情况下复活。
@MarcusS.Zarra Xcode 7 GM 但这可能并不重要。
1.好的,但你在第一句话中说的完全相反。也许你想纠正它。 2.请添加删除和撤消注册的代码。 4. 不能撤销不是最后一个操作的操作。它是一个带有 push 和 pop 的撤销堆栈,但没有“索引访问”。
【参考方案1】:
正如Amin Negm-Awad所指出的:
您无法撤消具有后续操作的操作。撤消 在许多情况下,预测行动是不可能的,当然也不是 支持的。 (即撤消对员工的删除不能带来 返回他们所属的部门。)您必须注册所有操作 或者没有,否则你与框架作斗争。它仍然是一个堆栈,并且 当我写下一条评论时,这将是一个堆栈。因此显然 您不能选择用于撤消的操作和不用于的操作 撤消。所以注册所有操作并使用撤消组。
【讨论】:
以上是关于CoreData NSUndoManager 关系问题的主要内容,如果未能解决你的问题,请参考以下文章
自动保存不适用于 UIManagedDocument 上的 NSUndoManager