7

我正在学习 Cocoa,并且我已经撤消了工作,没有太多麻烦。但是 setActionName: 方法让我很困惑。这是一个简单的示例:一个玩具应用程序,其窗口包含一个文本标签和两个按钮。按下开按钮,标签上显示“开”。按下关闭按钮,标签变为“关闭”。这是两个相关的方法(我为应用程序编写的唯一代码):

-(IBAction) turnOnLabel:(id)sender
{
    [[self undoManager] registerUndoWithTarget:self selector:@selector(turnOffLabel:) object:self];
    [[self undoManager] setActionName:@"Turn On Label"];
    [theLabel setStringValue:@"On"];
}

-(IBAction) turnOffLabel:(id)sender
{
    [[self undoManager] registerUndoWithTarget:self selector:@selector(turnOnLabel:) object:self];
    [[self undoManager] setActionName:@"Turn Off Label"];
    [theLabel setStringValue:@"Off"];
}

这是我的期望:

  • 我点击开按钮
  • 标签更改为“开”
  • 在编辑菜单中是“撤消打开标签”项
  • 我点击那个菜单项
  • 标签更改为“关闭”
  • 在编辑菜单中是“重做打开标签”项

事实上,除了最后一个之外,所有这些都按我的预期工作。编辑菜单中的项目显示为“重做关闭标签”,而不是“重做打开标签”。(当我单击该菜单项时,标签确实会变为 On,正如我所料,但这使菜单项的名称更加神秘。)

我有什么误解,我怎样才能让这些菜单项以我想要的方式显示?

4

3 回答 3

3

请记住:当您重做时,您的代码必须为 Undo 菜单项设置一个 actionName。

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

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

当您最初 setActionName:![[self undoManager] isUndoing],此 actionName 转到 Undo 菜单项。然后,当您选择撤消([[self undoManager] isUndoing] == YES,您未设置任何操作名称)时,undoManager 会自动将此操作名称设置为重做菜单项,并将先前的撤消操作名称设置为撤消菜单项。当您随后选择重做时,您仍然必须传递一个 actionName 才能转到撤消菜单项。

换句话说:只有当您的代码不是 Undoing 时才需要设置 actionNames(但您必须在最初调用或重做时设置)。

于 2011-08-13T08:19:52.897 回答
2

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

1)当与所选的控制相关联时,是执行其目标/动作序列(即,nsundomanager isundoingiSredoing方法将返回否)

2) 当您执行撤消操作时,而 turnOnLabel: 方法实际上是由 NSUndoManager 调用的(即 isUndoing = YES 和 isRedoing = NO)

3) 当你正在执行一个重做操作时,而 turnOnLabel: 方法实际上是被 NSUndoManager 调用的(即 isUndoing = NO 和 isRedoing = YES)

isUndoing  isRedoing    Action
-------------------------------------------------
   0           0        Turn On Label
   0           1        Turn On Label
   1           0        Turn Off Label
   1           1        <impossible state>
于 2011-03-03T07:23:21.193 回答
2

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

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

谁能解释为什么 NSUndoManager 需要我这样做,我会给出正确的答案。

于 2011-02-23T16:09:13.820 回答