【问题标题】:NSWindow returns nil (NSApplication)NSWindow 返回 nil (NSApplication)
【发布时间】:2015-10-06 16:26:56
【问题描述】:

我遇到了无法访问应用程序主窗口的问题, 因为它返回 nil

let window = NSApplication.sharedApplication().mainWindow

我发现了类似的问题:

How to get Main Window (App Delegate) from other class (subclass of NSViewController)?

但是做:

let window = (NSApplication.sharedApplication() as! NSArray).objectAtIndex(0)

似乎也不起作用。

我必须在 Storyboard 中乱来吗?

提前致谢。

更新:

我实际上是在尝试从 Objective-C 移植一些东西。

    NSWindow *mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
    NSLog(@"%@", mainWindow.contentViewController);

当放入NSViewController 中的viewDidLoad() 块时,这会返回一个正确的值,所以我猜NSApplication.sharedApplication() 有问题。

【问题讨论】:

    标签: macos swift nswindow


    【解决方案1】:

    如果主应用程序窗口在 macOS 上不活动,它也可以返回 nil。例如,我在制作拖放文件上传器时遇到了这个问题。如果窗口不在前面(在操作系统上),它将返回 nil。以下代码行将激活您的应用(放在前面)

    NSApp.activateIgnoringOtherApps(true)
    

    我还需要一个计时器来延迟我对 mainWindow 的调用。

    【讨论】:

      【解决方案2】:

      你可以这样做:

         func applicationDidBecomeActive(notification: NSNotification) {
      
              NSApplication.sharedApplication().mainWindow?.movable = false
          }
      

      【讨论】:

        【解决方案3】:

        来自the docs

        当应用的情节提要或 nib 文件尚未完成加载时,此属性中的值为 nil。当应用处于非活动或隐藏状态时,它也可能是nil

        所以,这完全是正常的事情,视情况而定。

        【讨论】:

        • 感谢您的回复。当点击视图 1 的表格单元格时,我试图为 view2 设置一个值。因此,它应该完成加载。为什么会这样?
        • 你的窗口是主窗口吗?如果它是 NSPanel,那么它拒绝成为 main,除非您覆盖 canBecomeMainWindow() 以返回 true。类似地,如果它没有标题栏并且不可调整大小,它将拒绝成为 main。
        • 作为我的Initial Controller,设置了NSWindowControllerNSWindowNSWindow 有一个标题栏,并且可以调整大小。我不确定NSPanel...从来没有在我的代码中使用过它。
        【解决方案4】:

        如果你的应用只包含一个窗口,或者总是从同一个窗口开始,甚至没有从内存中删除它,你可以使用这个代码:

        if let window = NSApp.windows.first {
            window.makeKeyAndOrderFront(self) // Or do something else
        }
        

        如果您在应用启动期间需要窗口,则应异步加载此代码,如下所示:

        DispatchQueue.main.async {
            if let window = NSApp.windows.first {
                window.makeKeyAndOrderFront(self)
            }
        }
        

        【讨论】:

          【解决方案5】:

          确保您的情节提要中有一个窗口作为初始控制器

          【讨论】:

            【解决方案6】:

            对我来说,接受的答案不起作用。 activate(ignoringOtherApps:) 的文档说:

            ...you shouldn’t assume the app will be active immediately after sending this message.
            

            因此,mainWindow 很可能会保留为nil。所以对我来说,以下工作:

            extension NSApplication {
              /// Activates the app so main window / key window are no longer `nil`. Pauses a bit between activations and keeps trying.
              /// - Parameter completion: completion called with the key / main window
              @objc public static func withKeyOrMainWindow(mainOnly: Bool = false, completion: @escaping (_ window: NSWindow)->Void) {
                DispatchQueue.main.async {
                  let window = mainOnly ? NSApplication.shared.mainWindow : NSApplication.shared.keyWindow ?? NSApplication.shared.mainWindow
                  if let window = window {
                    completion(window)
                  }
                  else {
                    // Activate the app
                    NSApp.activate(ignoringOtherApps: true)
                    
                    // Short delay
                    DispatchQueue.main.asyncAfter(deadline: .now()+0.2) {
                      NSApplication.withKeyOrMainWindow(completion: completion)
                    }
                  }
                }
              }
              
              /// Activates the app so main window is no longer `nil`. Pauses a bit between activations and keeps trying.
              /// - Parameter completion: completion called with the main window
              @objc public static func withMainWindow(completion: @escaping (_ window: NSWindow)->Void) {
                return withKeyOrMainWindow(mainOnly: true, completion: completion)
              }
            }
            

            用法:

            NSApplication.withKeyOrMainWindow { window in
              alert.beginSheetModal(for: window) { (response: NSApplication.ModalResponse) in
                    handler?(response)
              }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-02-18
              • 2019-06-20
              • 2017-12-16
              • 2014-09-27
              相关资源
              最近更新 更多