2015-11-30 47 views
1

我保持一些遺留代碼和autoenablesItems甚至工作,當它被提出與10.8 SDK,而不是10.7 SDK,對於某些菜單項目的一些關鍵相當於快捷鍵編譯停止工作。我的假設是,這是因爲這些菜單項處於禁用狀態。那些不再工作的NSMenuItems是那些人在那裏autoenablesItems已設置爲NO(我在通過屬性檢查器中爲子菜單中的廈門國際銀行以及編程通過查詢[NSMenu autoenablesItems]證實了這一子菜單的一部分。它基本上出現對[NSMenuItem setEnabled:]的調用沒有效果,因爲如果我在調用setEnabled:YES之後立即查詢[NSMenuItem isEnabled],狀態沒有改變,並且它仍然返回了isEnabled的NO。下面是帶輸出的代碼片段它產生:NSMenuItem的的setEnabled不設置爲NO NSMenu

printf("DEBUG: Current state of menu item is "); 
[nsMenuItem isEnabled] ? printf("enabled\n") : printf("DISABLED!\n"); 
printf("DEBUG: Current state of menu autoenablesItems is "); 
[nsMenu autoenablesItems] ? printf("YES\n") : printf("NO\n"); 

[nsMenuItem setEnabled:YES]; 

printf("DEBUG: Current state of menu after setting it is "); 
[nsMenuItem isEnabled] ? printf("enabled\n") : printf("DISABLED!\n"); 

輸出:

DEBUG: Current state of menu item is DISABLED! 
DEBUG: Current state of menu autoenablesItems is NO 
DEBUG: Current state of menu after setting it is DISABLED! 

我還噸ried繼承NSMenuItem並覆蓋setEnabled以查看是否有另一個調用正在覆蓋我的調用的setEnabled,但是沒有其他調用通過setEnabled進行。

如果我點擊子菜單的父菜單,然後它似乎正確的狀態,這些NSMenuItems得到啓用,但它不會通過我的setEnabled代碼來改變這種狀態。我試圖添加一個觀察者到子類上啓用嘗試和捕獲狀態設置爲啓用時,單擊父菜單上,但沒有提供任何洞察力,因爲觀察員只觸發我的電話setEnabled哪實際上並沒有改變這個狀態。

從閱讀Apple文檔可以看出,NSMenuItem的setEnabled應該工作,只要在父菜單上將autoenablesItems設置爲NO,但在這種情況下似乎不起作用,而且我不能找出原因。

在相同的代碼中,如果我使用10.7 SDK進行編譯(注意:這實際上是代碼庫的舊版本,所以還有其他的區別,但是這個特定的代碼是相同的),我確實看到該調用setEnabled更改NSMenuItem的狀態。當它在10.7版本中輸入這個代碼時,NSMenuItem已經處於啓用狀態,但是我嘗試將該調用更改爲setEnabled:NO,以確認它是否確實切換了isEnabled狀態,並且它的確如此,與10.8版本不同。

這是爲什麼不工作10.8任何想法?我也嘗試過10.9,但它也沒有在那裏工作。我一直無法嘗試10.10或10.11,因爲還有一些其他代碼需要更新才能使用較新的SDK進行編譯(同樣,這是相當古老的代碼)。

+0

當這些日誌被打,你確定那nsMenuItem實際上不是零?這會導致兩個日誌都打印爲NO。另一個攻擊途徑是在任何相關對象(目標,第一響應者)上定義菜單驗證方法,並查看是否調用了(1),並且(2)即使在自動啓用被轉向時也尊重其返回值關閉。有些可怕的事情正在發生,因爲這些東西都是舊代碼,並且在可可中運行良好很多年。偵探工作是需要的。 – bhaller

+0

我已經確認nsMenu和nsMenuItem不是零。我也證實,點擊頂層菜單項(nsMenu是子菜單)後,下一次調用代碼後,nsMenu和nsMenuItem仍然是相同的對象(調試器中的地址相同) ,然後isEnabled返回true。 nsMenuItem上的目標爲零,但有一個定義的操作。它在工作時也具有相同的狀態。 – user1176103

+0

當關鍵等價物起作用時,我們最終在定義的動作的代碼中(通過NSApplication的sendEvent,接着是NSObject的performSelector:withObject,然後是動作)。當等價關鍵字不起作用時,則從NSApplication的sendEvent中,我們先到NSWindow的sendEvent(首先通過子類的sendEvent),接着是NSWindow的_reallySendEvent:isDelayedEvent:後跟視圖的keyDown :.所以這個動作永遠不會被調用,我認爲這是因爲菜單項被禁用。 – user1176103

回答

0

不知道爲什麼SDK版本將沒關係,但你檢查InterfaceBuilder下的菜單,以確保它沒有設置爲「啓用」狀態的綁定?這將是這些物品被神祕禁用的另一種方式。

否則,菜單代表可以出從下你的其他代碼替換菜單項,或明確禁止的物品。還有一個NSMenuDelegate方法

- menuHasKeyEquivalent:forEvent:target:action: 

它得到在加速鍵被按下的情況下專門打電話,並且可以完全繞過菜單項的啓用/禁用狀態。

+0

要檢查綁定,你看看Bindings Inspector嗎?如果是這樣,我沒有看到「綁定到」在任何部分檢查。在代碼庫中的任何地方也沒有menuHasKeyEquivalent的實例,所以我不認爲這可能是問題。 – user1176103

+0

奇怪。我可以使用10.10和10.11 SDK以及一個簡單的測試程序來驗證,事情的工作方式與您所期望的相同 - 如果菜單中的autoEnablesItems處於關閉狀態,setEnabled和isEnabled將工作並返回正確的結果。 –

+0

要回答另一個問題 - 是的,請在選擇菜單項後查看綁定檢查器。 –

-1

簡單時使用此啓用/禁用菜單項

NSMenu *menu = [[NSMenu alloc] init]; 

添加禁用菜單項

[menu addItemWithTitle:@"DisableItem" action:nil keyEquivalent:@""]; 

添加使菜單項

[menu addItemWithTitle:@"EnableItem" action:@selector(method:) keyEquivalent:@""];