Реализация NSPopover на NSStatusItem

В настоящее время у меня есть NSStatusItem для строки состояния, которая инициализируется в awakeFromNib следующим образом:

    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    [statusItem setMenu:statusMenu];
    [statusItem setImage:statusImage];
    [statusItem setAlternateImage:statusHighlightedImage];
    [statusItem setHighlightMode:YES];
    [statusItem setTarget:self];

У меня есть NSMenu, который открывается при нажатии на значок. Один из вариантов при нажатии должен открыть NSPopover из значка строки состояния. Для этого у меня есть этот код, который подключается к пункту меню через Interface Builder:

- (IBAction)prefs:(id)sender {    
    NSRectEdge prefEdge = NSMaxYEdge;

    [[self pop] showRelativeToRect:[[statusItem view] bounds]
                          ofView:[statusItem view]
                   preferredEdge:prefEdge];
}

Однако, когда я щелкаю элемент меню, который должен открыть всплывающее окно, ничего не происходит. Есть ли какая-то конкретная причина, по которой это может быть так? Насколько я могу судить, это должно быть возможно сделать.

Заранее спасибо. Я просмотрел Stack Overflow как мог, но если есть действительно повторяющийся вопрос, пожалуйста, дайте мне ссылку на него.

К вашему сведению: переменная statusItem — это NSStatusItem.


person Josh    schedule 27.12.2012    source источник
comment
Вы должны добавить код для NSMenu   -  person IluTov    schedule 27.12.2012
comment
Вызывается ли этот метод -prefs:? [self pop] и [statusItem view] не равны нулю?   -  person paulmelnikow    schedule 27.12.2012
comment
@noa прав, попробуйте что-нибудь записать и проверьте, не возвращает ли self.pop nil.   -  person IluTov    schedule 27.12.2012
comment
@NSAddict NSMenu фактически реализован непосредственно в IB. Возможно, мне следует реализовать это программно?   -  person Josh    schedule 27.12.2012
comment
@ Джош, нет, все должно быть в порядке, если ты правильно подключил его. Попробуйте записать что-нибудь в prefs:   -  person IluTov    schedule 27.12.2012
comment
О, [self pop] возвращает ноль. Может быть, я даже неправильно реализую Popover. Что вы думаете, ребята? @ноа   -  person Josh    schedule 27.12.2012
comment
Я не использовал NSPopover, но, возможно, вам просто нужно его создать. Попробуйте self.pop = [[NSPopover alloc] init]; в -awakeFromNib.   -  person paulmelnikow    schedule 27.12.2012
comment
@Нет, если я это сделаю, то в консоли будет напечатано: 2012-12-26 17:58:31.805[821:303] Возникло неперехваченное исключение 2012-12-26 17:58:31.807[821:303] -[NSPopover showRelativeToRect:ofView:preferredEdge:]: представлено нулевое представление. Вы должны предоставить представление.   -  person Josh    schedule 27.12.2012
comment
Или используйте поповер и контроллер просмотра в IB.   -  person Ramy Al Zuhouri    schedule 27.12.2012
comment
@RamyAlZuhouri Я считаю, что именно так я это и реализовал, если только я не сделал что-то неправильно.   -  person Josh    schedule 27.12.2012
comment
Бьюсь об заклад, что вместо привязки всплывающего окна вы привязали контроллер представления всплывающего окна.   -  person Ramy Al Zuhouri    schedule 27.12.2012
comment
@RamyAlZuhouri, как мне проверить, правильно ли он связан?   -  person Josh    schedule 27.12.2012
comment
Похоже, вам нужно либо использовать настраиваемое представление в элементе статуса, либо найти другой способ получить позицию в элементе статуса.   -  person paulmelnikow    schedule 27.12.2012
comment
Если это не сработает, взгляните на MAAttachedWindow Мэтта Геммелла.   -  person TheAmateurProgrammer    schedule 27.12.2012
comment
Вам нужно самостоятельно установить представление, чтобы [statusItem view] возвращал не-nil.   -  person Wevah    schedule 27.12.2012
comment
Попробуйте сделать это еще раз, щелкните правой кнопкой мыши делегат приложения, найдите ivar, перетащите его, удерживая клавишу Ctrl, в всплывающее окно (а не в контроллер всплывающего окна).   -  person Ramy Al Zuhouri    schedule 27.12.2012
comment
@RamyAlZuhouri попробовал еще раз, чтобы убедиться, что с моей стороны все в порядке.   -  person Josh    schedule 27.12.2012
comment
@Wevah, мой собственный вид?   -  person Josh    schedule 27.12.2012
comment
Потом покажи аксессор self.pop, что это? Там наверняка ошибка.   -  person Ramy Al Zuhouri    schedule 27.12.2012


Ответы (2)


Вам нужно установить представление самостоятельно, используя [statusItem setView:] для [statusItem view], чтобы вернуть не-nil.

Если вы не возражаете против использования частного API, вы можете попробовать вместо этого вызвать [statusItem _button], хотя это будет запрещено, если вы планируете отправлять в App Store.

person Wevah    schedule 27.12.2012
comment
Я пытался использовать _button просто для того, чтобы посмотреть, сработает ли это, но это не сработало. Если я не совершаю легкую ошибку, настройка представления, похоже, не работает. Он просто переопределяет текущий вид элемента состояния (поэтому он исчезает из строки меню). - person Josh; 27.12.2012
comment
Да, это то, что он делает. - person Wevah; 27.12.2012
comment
Хм. Не уверен, почему это не сработает, даже когда я создам новое представление. - person Josh; 27.12.2012
comment
Кнопка больше не является частной, и ее даже рекомендуется использовать как общедоступную собственность, начиная с MacOS 10.10. - person Motti Shneor; 14.06.2021
comment
setView: устарело.) - person Wevah; 14.06.2021

Я не знаю, была ли эта проблема решена уже, но у меня есть несколько заметок.

  1. Первый шаг — проверить (сгенерировать NSLog или остановиться в точке останова в отладчике), что ваш пункт меню действительно работает и что prefs: IBAction вызывается.
  2. Я не знаю вашего дизайна пользовательского интерфейса, но имеет смысл показывать всплывающее окно относительно NSMenuItem, который приказал ему появиться, а не относительно NSStatusItem. Так что используйте [(NSMenuItem *)sender view] в качестве якоря и его границ.
  3. попробуйте отобразить всплывающее окно из другого места в вашем приложении - просто чтобы убедиться, что фактическое всплывающее окно в порядке и может отображаться.
person Motti Shneor    schedule 14.06.2021