2011-02-23 44 views
5

我正在學習可可,並且我已經完成撤銷工作,沒有太多麻煩。但是setActionName:方法令我困惑。這裏有一個簡單的例子:一個玩具應用程序,其窗口包含一個文本標籤和兩個按鈕。按開啓按鈕,標籤顯示「開」。按下「關」按鈕,標籤更改爲「關」。這裏有兩個相關的方法(我寫的應用程序的唯一代碼):如何讓NSUndoManager的撤銷/重做動作名稱正常工作?

-(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,正如我所料,但這使得菜單項的名稱更加神祕。 ?條款顯示我希望他們

回答

2

記住:當你重做,你的代碼必須爲撤消菜單項目actionName。

當你撤消重做,重做菜單項actionName自動設置。

setActionName:僅更改撤消菜單項重做菜單項actionName是自動的。

當你最初setActionName:![[self undoManager] isUndoing],這個actionName轉到撤消菜單項。當您選擇撤消([[self undoManager] isUndoing] == YES,您沒有設置任何操作名稱)時,自動撤消管理器將此操作名稱設置爲重做菜單項,並將上一次撤消操作名稱設置爲撤消菜單項。當您選擇重做時,您仍然必須傳遞一個actionName才能進入「撤消」菜單項。

換言之:只有當代碼不是撤消時(但您必須在最初調用或重做時設置),您必須設置actionNames。

+0

我只是在這裏提到'setActionName:'的功能而不是'redoActionName:'或'undoActionName:'的功能。 – Vassilis 2011-08-13 08:35:53

1

看一些示例代碼後的樣子,我可以通過添加條件的setActionName解決這個問題:在每個方法調用,就像這樣:

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

我會給出正確的答案,誰能解釋爲什麼NSUndoManager需要我這樣做。

2

因爲你的turnOnLabel:方法可以被調用三種可能的方式:

1)時所選擇的與正在執行其靶/動作序列(相關聯的控制即NSUndoManager isUndoing isRedoing方法將返回NO )

2)時要執行撤消操作,並且turnOnLabel:方法實際上是由NSUndoManager(即,isUndoing = YES和isRedoing =否)

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> 
+0

克拉倫斯 - 感謝您的答案。我明白你說的是什麼,但我不明白爲什麼它會對setActionName產生影響:它是在撤銷時,重做時還是在首次執行時調用的。無論哪種方式,就我所見,正在向撤銷/重做堆棧中添加或移除操作,而且無論如何操作應具有相同的名稱。 – 2011-03-04 14:35:42