2015-11-30 3 views
1
.

. Я поддерживаю некоторый унаследованный код, и когда он был скомпилирован с 10.8 SDK, а не 10.7 SDK, некоторые ключевые эквивалентные ярлыки для определенных пунктов меню перестал работать. Моя гипотеза заключается в том, что это связано с тем, что эти пункты меню находятся в отключенном состоянии. NSMenuItems, которые больше не работают, являются теми, которые были частью подменю, где autoenablesItems был установлен в NO (я подтвердил это в xib с помощью инспектора атрибутов для этого подменю, а также программно, запросив [NSMenu autoenablesItems]. что вызов [NSMenuItem setEnabled:] не действует, потому что если я запрошу [NSMenuItem isEnabled] сразу после вызова setEnabled: YES, состояние не изменилось и оно все равно возвращает NO для isEnabled. Вот фрагмент кода с выходом он генерирует:SetEnabled NSMenuItem не работает даже с автозапусками. Элементы установлены в 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 subclassing NSMenuItem и переопределить setEnabled, чтобы узнать, был ли произведен еще один вызов setEnabled, который переписывал мой вызов, но нет других вызовов, которые проходят через setEnabled.

Если я нажму на родительское меню подменю, то, похоже, будет исправлено состояние, и эти элементы NSMenuItems будут включены, но этот код не будет меняться, чтобы изменить это состояние. Я попытался добавить наблюдателя в подкласс, включенный, чтобы попытаться поймать, когда состояние было настроено на включение, когда вы нажимаете на родительское меню, но это не давало никакого представления ни о том, что наблюдатель был вызван только для моих вызовов setEnabled, которые фактически не меняют состояние.

Из того, что я могу сказать, прочитав документацию Apple, setEnabled для NSMenuItem должен работать до тех пор, пока autoenablesItems установлен в NO в родительском меню, но это, похоже, не работает в этом случае, и я не могу выяснить почему.

В том же коде, если я использую SDK 10.7 для компиляции (предостережение: на самом деле это более старая версия базы кода, так что есть и другие отличия, но этот конкретный код один и тот же), я вижу что вызов setEnabled изменяет состояние NSMenuItem. Когда он вводит этот код в сборке 10.7, NSMenuItem уже находится в разрешенном состоянии, но я попытался изменить вызов на setEnabled: NO, чтобы подтвердить, действительно ли это действительно переключило состояние isEnabled, и это произошло, в отличие от сборки 10.8 ,

Любые идеи, почему это не работает в 10.8? Я также пробовал с 10.9, и он тоже не работал. Я не смог попробовать 10.10 или 10.11, так как есть еще один код, который нуждается в обновлении, чтобы его можно было скомпилировать с новыми SDK (опять же, это довольно старый унаследованный код).

+0

Когда эти журналы попали, вы уверены, что nsMenuItem на самом деле ничто? Это приведет к тому, что NO будет напечатано для обоих журналов. Другой аспект атаки - определить метод проверки меню на любом объекте (цель, первый ответчик) и увидеть, вызвано ли оно (1), и (2) соблюдается его возвращаемое значение, даже когда автозавершение повернуто выкл. Что-то рыбное происходит, потому что этот материал - старый код, и он много работал в Cocoa. Детективная работа - это то, что нужно. – bhaller

+0

Я подтвердил, что nsMenu и nsMenuItem не ноль. Я также подтвердил, что после нажатия на элемент меню верхнего уровня (что nsMenu является подменю), то в следующий раз после этого, что код вызывается, nsMenu и nsMenuItem по-прежнему остаются теми же объектами (один и тот же адрес в отладчике) , и thenEnabled возвращает true. Цель на nsMenuItem равна нулю, но есть определенное действие. Он имеет такое же состояние, когда он работает. – user1176103

+0

Когда ключевой эквивалент работает, мы заканчиваем код определенного действия (через NSEpplication's sendEvent, за которым следует NSObject's Performer: withObject, за которым следует действие). Когда эквивалент ключа не работает, то из sendEvent NSApplication мы переходим к sendEvent NSWindow (сначала через sendEvent подкласса), а затем через _reallySendEvent NSWindow: isDelayedEvent: за ним следует keyDown :. Поэтому действие никогда не вызывается, и я полагаю, это потому, что пункт меню отключен. – user1176103

ответ

0

Не знаете, почему версия SDK имеет значение, но проверили ли вы меню в InterfaceBuilder, чтобы убедиться, что у него нет привязок, настроенных для состояния «включения»? Это было бы другим способом, чтобы предметы стали таинственно-отключенными.

В противном случае делегат меню может заменять элементы меню из-под другого кода или явно отключать элементы. Там также метод NSMenuDelegate

- menuHasKeyEquivalent:forEvent:target:action: 

который вызывается именно в тех случаях, когда был нажат ключ акселератора, и который может полностью обойти включенное/выключенное состояние пунктов меню.

+0

Чтобы проверить привязки, вы смотрите на инспектора Bindings? Если это так, я не вижу «Привязать» к любому из разделов. Там также нет экземпляра menuHasKeyEquivalent нигде в базе кода, поэтому я не думаю, что это может быть проблемой. – user1176103

+0

Странно. Я могу проверить, что с 10.10 и 10.11 SDK и тривиальной тестовой программой все работает так, как вы ожидали, - если autoEnablesItems отключен для меню, setEnabled и isEnabled работают и возвращают правильный результат. –

+0

Чтобы ответить на другой вопрос - да, посмотрите в инспекторе Bindings после выбора пункта меню. –

-1

простого использование этого для включения/пунктов ограниченного меню

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

добавить отключить пункт меню

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

добавить включить пункт меню

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

 Смежные вопросы

  • Нет связанных вопросов^_^