测试设置:
// Create a clean context for this test.
NSManagedObjectContext *cleanContext = [MyContextManager sharedInstance] newMOC];
// Create a core data object.
MyCoreDataObject *myObject = [MyCoreDataObject insertNewObjectInMoc:cleanContext];
myObject.name = @"Test Name 1";
// Create an undo manager - set on the context.
cleanContext.undoManager = [NSUndoManager new];
// Turn off automatic grouping
cleanContext.undoManager.groupsByEvent = NO;
[cleanContext.undoManager beginUndoGrouping];
myObject.name = @"Test Name 2";
XCTAssertEqualObjects(myObject.name, @"Test Name 2", @"Setting name failed");
// End undo grouping
[cleanContext.undoManager endUndoGrouping];
// Undo the group that has just been created
[cleanContext.undoManager undoNestedGroup];
XCTAssertEqualObjects(myObject.name, @"Test Name 1", @"Undo failed");
我看到撤消管理器有一个私有的调用堆栈,我可以通过[cleanContext.undoManager performSelector:@selector(_undoStack)]
访问 在查看它时,即使我已经关闭了按事件分组,也有新的撤消分组我没有添加。
这会导致很多痛苦 - 即使我正确管理开始和结束撤消组,也会发生诸如NSUndoManager is in invalid state
的错误。
在核心数据对象上设置属性是否会自动添加它们,而不考虑按事件分组设置?
有没有人设法使用内置的撤消管理器创建稳定的撤消功能?
我没有看到你所有的代码,但是如果你在测试用例中调用undo()
,它将撤消到目前为止你的方法中的所有内容。(实际上是一件值得测试的好东西)
每个运行循环都会创建自己的撤消组。测试方法位于该运行循环中。调用undo()
将关闭该组,然后撤消所有操作。
如果要尝试测试撤消功能,则需要调用undoNestedGroup()
。(我的例子是 Swift 的,但很简单)
func testInsertUndo() {
doc.undoManager?.beginUndoGrouping()
let r1 = doc.createRegion("testRegion1")
doc.undoManager?.endUndoGrouping()
doc.undoManager?.beginUndoGrouping()
doc.createRegion("testRegion2")
doc.undoManager?.endUndoGrouping()
// undo() will close surrounding run-loop undo group and then undo the whole thing
doc.undoManager?.undoNestedGroup()
XCTAssert(doc.regionCount == 1, "undo should remove last region (doc.regionCount) != 1")
for (index, r) in doc.regionEnumerator {
XCTAssert(index == 0 && r === r1, "first region remains")
}
}