Swift5 macOS下如何编程将App窗口显示在主屏幕而非外接屏[Xcode15]
问题1:viewDidLoad中调整窗口位置无效的原因
viewDidLoad调用时,视图仅完成加载,尚未关联到所在的NSWindow实例,此时self.view.window的值为nil,所有调整窗口的代码都不会生效。
可行的窗口指定屏幕显示方案
你可以在NSViewController的viewDidAppear方法中执行窗口位置调整,或者直接在NSWindowController层面做配置,Swift 5下的可用代码如下:
方案1:在ViewController中调整
override func viewDidAppear() { super.viewDidAppear() guard let mainScreen = NSScreen.screens.first, let window = self.view.window else { return } // 计算窗口在主屏幕居中的位置 let targetFrame = mainScreen.visibleFrame let windowSize = window.frame.size let targetOrigin = NSPoint( x: targetFrame.midX - windowSize.width / 2, y: targetFrame.midY - windowSize.height / 2 ) window.setFrameOrigin(targetOrigin) }
方案2:在WindowController中调整(推荐)
如果是自定义NSWindowController,可以重写windowDidLoad方法:
override func windowDidLoad() { super.windowDidLoad() guard let mainScreen = NSScreen.screens.first, let window = self.window else { return } let targetFrame = mainScreen.visibleFrame let windowSize = window.frame.size let targetOrigin = NSPoint( x: targetFrame.midX - windowSize.width / 2, y: targetFrame.midY - windowSize.height / 2 ) window.setFrameOrigin(targetOrigin) }
问题2:ViewController中无法控制窗口显隐的原因
你在applicationDidFinishLaunching中创建的windowController是局部变量,函数执行完成后该实例会被ARC自动释放,对应的窗口也会被销毁,ViewController中拿到的self.view.window已经是无效对象,自然无法控制显隐。
修正方案
在AppDelegate中添加全局属性持有windowController的引用,修正后的AppDelegate代码如下:
// AppDelegate.swift import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { // 新增属性持有windowController,避免被自动释放 var mainWindowController: NSWindowController? func applicationDidFinishLaunching(_ aNotification: Notification) { let storyboard = NSStoryboard(name: "Main", bundle: nil) if let windowController = storyboard.instantiateController(withIdentifier: "mainWindow") as? NSWindowController { // 赋值给全局属性持有 self.mainWindowController = windowController windowController.window?.level = .floating guard let mainScreen = NSScreen.screens.first else { return } let targetFrame = mainScreen.visibleFrame let windowSize = windowController.window?.frame.size ?? .zero let targetOrigin = NSPoint( x: targetFrame.midX - windowSize.width / 2, y: targetFrame.midY - windowSize.height / 2 ) windowController.window?.setFrameOrigin(targetOrigin) windowController.window?.zoom(self) windowController.window?.backgroundColor = .white windowController.window?.isMovable = false windowController.window?.styleMask.remove(.resizable) windowController.showWindow(self) } else { print("failed to show the window") } } }
修改后即可在ViewController中通过self.view.window?.setIsVisible()正常控制窗口显隐。
内容的提问来源于stack exchange,提问作者user8460166
相关产品推荐
相关产品推荐

