Cocoa 我如何才能成为NSUndoManager';s撤消/重做操作名称是否正常工作?

Cocoa 我如何才能成为NSUndoManager';s撤消/重做操作名称是否正常工作?,cocoa,undo,nsundomanager,Cocoa,Undo,Nsundomanager,我在学可可,而且我工作起来没有太多麻烦。但是setActionName:方法让我感到困惑。这里有一个简单的例子:一个玩具应用程序,其窗口包含一个文本标签和两个按钮。按下“打开”按钮,标签上显示“打开”。按下“关闭”按钮,标签变为“关闭”。以下是两个相关的方法(我为应用程序编写的唯一代码): 以下是我的期望: 我点击“打开”按钮 标签改为“开” “编辑”菜单中有“撤消打开标签”项 我点击那个菜单项 标签改为“关闭” “编辑”菜单中的“重做打开标签”项 事实上,除了上一个,所有这些都像我期望的那

我在学可可,而且我工作起来没有太多麻烦。但是setActionName:方法让我感到困惑。这里有一个简单的例子:一个玩具应用程序,其窗口包含一个文本标签和两个按钮。按下“打开”按钮,标签上显示“打开”。按下“关闭”按钮,标签变为“关闭”。以下是两个相关的方法(我为应用程序编写的唯一代码):

以下是我的期望:

  • 我点击“打开”按钮
  • 标签改为“开”
  • “编辑”菜单中有“撤消打开标签”项
  • 我点击那个菜单项
  • 标签改为“关闭”
  • “编辑”菜单中的“重做打开标签”项
事实上,除了上一个,所有这些都像我期望的那样工作。“编辑”菜单中的项显示“重做关闭标签”,而不是“重做打开标签”。(如我所料,当我单击该菜单项时,标签确实会打开,但这使得菜单项的名称更加神秘。)


我误解了什么?我如何才能让这些菜单项以我希望的方式显示?

在查看了一些示例代码后,我能够通过在每个方法中的setActionName:调用中添加一个条件来解决这个问题,如下所示:

if (![[self undoManager] isUndoing])
    [[self undoManager] setActionName:@"Turn On Label"];

我会给任何人一个正确的答案,谁能解释为什么NSUndoManager需要我这么做

因为turnOnLabel:方法可以通过三种可能的方式调用:

1) 当所选控件关联的控件正在执行其目标/操作序列时(即,NSUndoManager isUndoing和isRedoing方法将返回NO)

2) 执行撤消操作时,NSUndoManager实际上正在调用turnOnLabel:方法(即isUndoing=YES和isRedoing=NO)

3) 当您执行重做操作时,NSUndoManager实际上正在调用turnOnLabel:方法(即isUndoing=NO和isRedoing=YES)

isUndoing isRedoing操作
-------------------------------------------------
0打开标签
0 1打开标签
10关闭标签
1           1        

记住:重做时,代码必须为“撤消”菜单项设置操作名。

当您撤消或重做时,重做菜单项中的actionName将自动设置。

setActionName:
仅更改撤消菜单项。重做菜单项actionName是自动的

当您开始时
设置操作名:
时![[self-undoManager]isUndoing]
,此操作名将转到撤消菜单项。当您选择撤消(
[[self undoManager]isUndoing]==YES
,您不设置任何操作名)撤消管理器自动将此操作名设置为重做菜单项,将上一个撤消操作名设置为撤消菜单项。然后选择重做时,仍需传递actionName才能转到“撤消”菜单项


换句话说:只有在代码未撤消时才需要设置ActionName(但必须在最初调用或重做时设置)。

Clarence感谢您的回答。我理解你所说的,但我不明白为什么setActionName会有不同:是在撤消、重做还是第一次执行时调用它。无论哪种方式,据我所知,正在向撤消/重做堆栈中添加或从中删除一个操作,并且该操作应该具有相同的名称。我在这里只提到
setActionName:
的功能,而不是
redActionName:
undoActionName:
if (![[self undoManager] isUndoing])
    [[self undoManager] setActionName:@"Turn On Label"];
isUndoing  isRedoing    Action
-------------------------------------------------
   0           0        Turn On Label
   0           1        Turn On Label
   1           0        Turn Off Label
   1           1        <impossible state>