NSUndoManager:在一个运行循环周期中分离多个更改

Nic*_*sky 3 macos xcode cocoa objective-c nsundomanager

我正在使用[undoManager registerUndoWithTarget ::]向撤消堆栈添加一些更改。但是,有时会发生,在一个运行循环周期中,两个更改被添加到同一组中,因此它们立即被还原,这不是我想要的行为。我想将这两个更改分开,以在撤消堆栈中包含两个项目。如何正确实现呢?使用[NSObject performSelector:]在下一个运行循环周期中调用第二次撤消附加操作,或其他方法?

谢谢。

小智 5

您已经注意到,默认情况下,默认情况下会NSUndoManager在一个运行循环周期内将撤消操作自动分组。但是,您可以更改该行为:-[NSUndoManager setGroupsByEvent:]如果发送NO参数,将禁用自动分组。请注意,您需要确保在撤消管理器执行-undo或之前关闭所有组-undoNestedGroup。由于其他Cocoa类可能希望在不显式创建组的情况下注册撤消操作,因此可以在注册撤消组之前禁用自动分组,而在注册这些组后重新启用。

例如:

- (void)someMethod {
    NSUndoManager *undoManager = …; // for example, [[self window] undoManager]
    [undoManager setGroupsByEvent:NO];
    {
        [undoManager beginUndoGrouping];
        {
            [undoManager registerUndoWithTarget:modelObject selector:@selector(setString1:) object:[modelObject string1]];
            [modelObject setStringValue:newValue1];
            [undoManager setActionName:@"String 1 Change"];
        }
        [undoManager endUndoGrouping];


        [undoManager beginUndoGrouping];
        {
            [undoManager registerUndoWithTarget:modelObject selector:@selector(setString2:) object:[modelObject string2]];
            [modelObject setString2:newValue3];

            [undoManager registerUndoWithTarget:modelObject selector:@selector(setString3:) object:[modelObject string3]];
            [modelObject setString3:newValue3];

            [undoManager setActionName:@"Strings 2 and 3 Change"];
        }
        [undoManager endUndoGrouping];
    }
    [undoManager setGroupsByEvent:YES];
}
Run Code Online (Sandbox Code Playgroud)

-someMethod三个变化适用于modelObject,修改它的string1string2string3特性。改变施加到string1是一个撤消组的一部分,并且使更改string2string3是另一个撤消基团的一部分。这两个组都包含在一个块中,其中,对于当前运行循环周期,撤消管理器不会将默认撤消组中的所有操作分组。执行此方法后,第一个撤消操作将同时撤消string2和所做的string3更改,随后的撤消操作将撤消应用于的更改string1,前提是没有另一个撤消组将它们围起来。

我使用C块{}使这两个层次结构(没有按事件和撤消组进行分组)清晰可见。

注:NSUndoManager不是线程安全的。