NSPopover для запуска в отсоединенном состоянии

Есть ли способ заставить NSPopover запускаться в отсоединенном состоянии? Я вижу только isDetached, которое является свойством только для чтения для состояния всплывающего окна, и метод NSPopoverDelegate detachableWindow(forPopover:), который позволяет мне переопределить создаваемое окно. Я хотел бы, по сути, нажать кнопку и запустить NSPopover в состоянии, показанном на этой фотографии.

Стиль этого окна точно соответствует требованиям продукта, и я не могу найти какие-либо настройки стиля NSWindow, которые заставляли бы окно делать что-то подобное (ни NSPanel)

Эта функция отдельного всплывающего окна кажется особенной, поскольку она:

  1. немодальный, но остается над основным приложением. Возможность по-прежнему взаимодействовать с основным приложением, как в сообщениях, как вы все еще можете щелкать и набирать новое сообщение.
  2. Щелчок по другому приложению, AppFoo, помещает как основное приложение, так и вспомогательное окно позади AppFoo.
  3. Вспомогательное окно можно перемещать, оно не скрывается при деактивации приложения (выбирается другое приложение).
  4. Имеет маленький родной серый крестик слева вверху.

Отключенная кнопка NSPopover из сведений в сообщениях


person Kirkova    schedule 25.06.2018    source источник


Ответы (2)


Вот в чем хитрость. Используйте требуемый метод делегата detachableWindowForPopover:, чтобы сделать всю работу за вас, например:

- (void) showPopoverDetached
{
    NSWindow* detachedWindow = [self detachableWindowForPopover:nil];

    [detachedWindow.windowController showWindow:nil];
}

Кажется, что инженеры Apple реализовали detachableWindowForPopover: довольно умным способом, я думаю, он использует класс контроллера представления контента и всегда будет создавать экземпляр отдельного окна, подобный синглтону. Как только detachableWindowForPopover: вызывает представленный экземпляр окна, он будет повторно использоваться независимо от того, когда и почему он вызывается, вызывается ли он напрямую (из функции, подобной моему примеру выше) или косвенно (например, когда вы перетаскиваете, отсоединяете всплывающее окно от его исходного должность)

Таким образом, они могут предотвратить отсоединение всплывающего окна «дважды», и мы также можем реализовать отсоединенный способ программно, отличная работа с их стороны!

person Hofi    schedule 03.12.2018
comment
Я новичок в Mac dev и не совсем понимаю решение. Я реализовал popoverShouldDetach для возврата true в моем NSPopoverDelegate, и я могу перетащить всплывающее окно, чтобы отсоединить его от выбранного NSView, к которому он изначально прикреплен (используя popover.show(relativeTo ...). Однако вызов detachableWindowForPopover напрямую означает, что мне нужно реализовать его в моем делегате popover, верно? В настоящее время он реализован просто как return nil. - person Josh; 27.01.2019
comment
сформировать справку detachableWindowForPopover: если делегата нет, делегат не реализует этот метод или делегат возвращает nil, всплывающее окно не будет отображаться отдельно. так что да, вам нужно реализовать метод делегата, он будет вызываться, когда пользователь перетаскивает всплывающее окно из его исходного состояния, а также вы можете вызвать его в любое время, чтобы изначально показать его в отсоединенном состоянии. - person Hofi; 28.01.2019
comment
я тоже не мог заставить предложение работать. все, что он будет делать, это открывать дополнительное окно, не имеющее связи с всплывающим окном. проверено 10.14 - person user1259710; 01.09.2019

Если вы не возражаете против вызова частного API, на самом деле это довольно просто:

let detach = NSSelectorFromString("detach")
if popover.responds(to: detach) {
    popover.perform(detach)
}

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

person DarkDust    schedule 08.04.2020