[英]How to open a window from a menu bar popover using SwiftUI on MacOS
[英]How to access macOS NSApp popover property
我在我的 macOS 應用程序的主生命周期文件中初始化了一個彈出窗口:
class AppDelegate: NSObject, NSApplicationDelegate{
var statusItem: NSStatusItem?
var popOver = NSPopover()
var authentication = Authentication()
func applicationDidFinishLaunching(_ notification: Notification) {
let menuView = MenuView().environmentObject(authentication)
popOver.behavior = .transient
popOver.animates = true
popOver.contentViewController = NSViewController()
popOver.contentViewController?.view = NSHostingView(rootView: menuView)
popOver.contentViewController?.view.window?.makeKey()
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let MenuButton = statusItem?.button{
// MenuButton.image = NSImage(systemSymbolName: "arrow.up.doc", accessibilityDescription: nil)
MenuButton.image = NSImage(named: NSImage.Name("icon_2"))
// MenuButton.image?.isTemplate = true
MenuButton.action = #selector(MenuButtonToggle)
}
if let window = NSApplication.shared.windows.first {
window.close()
}
}
@objc func MenuButtonToggle(sender: AnyObject? = nil){
@Environment(\.openURL) var openURL
if popOver.isShown{
popOver.performClose(sender)
}
else{
if let menuButton = statusItem?.button{
NSApplication.shared.activate(ignoringOtherApps: true)
self.popOver.show(relativeTo: menuButton.bounds, of: menuButton, preferredEdge: NSRectEdge.minY)
}
}
}
@objc func closePopover(_ sender: AnyObject? = nil) {
popOver.performClose(sender)
}
@objc func togglePopover(_ sender: AnyObject? = nil) {
if popOver.isShown {
closePopover(sender)
} else {
MenuButtonToggle(sender: sender)
}
}
}
我只是想知道如何在我的 AppDelegate 之外訪問popOver
屬性,更具體地說是在我的 SwiftUI 代碼的 rest 中。 我需要能夠在發生某些事情后關閉popOver
,例如:
checkFile(localURL: url, completion: { res, error in
// Close popover
// I assume it'll be something like NSApplication.shared.....
})
我的完整應用程序生命周期如下:
import SwiftUI
import Firebase
import Preferences
import Purchases
@main
struct ExampleApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
MenuView()
.environmentObject(self.delegate.authentication)
}
WindowGroup("Login") {
LoginView()
.environmentObject(self.delegate.authentication)
}.handlesExternalEvents(matching: Set(arrayLiteral: "LoginView"))
Settings{
SettingsView()
.environmentObject(self.delegate.authentication)
}
WindowGroup("Settings") {
SettingsView()
.environmentObject(self.delegate.authentication)
}.handlesExternalEvents(matching: Set(arrayLiteral: "SettingsView"))
}
}
class AppDelegate: NSObject, NSApplicationDelegate{
var statusItem: NSStatusItem?
var popOver = NSPopover()
var authentication = Authentication()
func applicationDidFinishLaunching(_ notification: Notification) {
let menuView = MenuView().environmentObject(authentication)
popOver.behavior = .transient
popOver.animates = true
popOver.contentViewController = NSViewController()
popOver.contentViewController?.view = NSHostingView(rootView: menuView)
popOver.contentViewController?.view.window?.makeKey()
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let MenuButton = statusItem?.button{
// MenuButton.image = NSImage(systemSymbolName: "arrow.up.doc", accessibilityDescription: nil)
MenuButton.image = NSImage(named: NSImage.Name("icon_2"))
// MenuButton.image?.isTemplate = true
MenuButton.action = #selector(MenuButtonToggle)
}
if let window = NSApplication.shared.windows.first {
window.close()
}
}
@objc func MenuButtonToggle(sender: AnyObject? = nil){
@Environment(\.openURL) var openURL
if popOver.isShown{
popOver.performClose(sender)
}
else{
if let menuButton = statusItem?.button{
NSApplication.shared.activate(ignoringOtherApps: true)
self.popOver.show(relativeTo: menuButton.bounds, of: menuButton, preferredEdge: NSRectEdge.minY)
}
}
}
@objc func closePopover(_ sender: AnyObject? = nil) {
popOver.performClose(sender)
}
@objc func togglePopover(_ sender: AnyObject? = nil) {
if popOver.isShown {
closePopover(sender)
} else {
MenuButtonToggle(sender: sender)
}
}
}
您可以使用NSApplication.shared
或NSApp
訪問應用程序實例(兩者都引用應用程序實例,並且都記錄在 NSApplication 的頁面上)。 一旦你有了它,你就可以獲得委托,例如:
let delegate = NSApp.delegate as! AppDelegate
(強制轉換委托似乎是安全的,因為您大概知道 a) 應用程序委托存在,以及 b) 它的類型是什么。)
擁有委托后,只需使用它來獲取彈出窗口:
let popover = delegate.popover
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.