我正在使用 NSWindowController 来实现首选项窗口。 Apple 的文档指出,默认情况下 Controller 和窗口不会被释放,因为不必重新加载所有内容很有用,这是有道理的。但是他们的文档继续说您可以覆盖该行为,但没有解释如何覆盖。

苹果的文档:

When a window is closed and it is part of a document-based
application, the document  removes the window’s window
controller from its list of window controllers. This results
in the system deallocating the window controller and the
window, and possibly the NSDocument object itself. When a
window controller is not part of a document-based application,
closing the window does not by default result in the
deallocation of the window or window controller. This is the
desired behavior for a window controller that manages something
like  an inspector; you shouldn’t have to load the nib file
again and re-create the objects the  next time the user requests
the inspector.

If you want the closing of a window to make both
window and window controller go away when it isn’t
part of a document, your subclass of NSWindowController
can observe the NSWindowWillCloseNotification notification
or, as the window delegate, implement the windowWillClose: method.

我找不到任何解释 windowWillClose: 方法中“实现”什么的地方。

窗口 Controller 可以在这里看到:
https://github.com/gngrwzrd/gwpreferences/blob/master/GWPreferences/GWPreferences/GWPreferences/GWPrefsWindowController.m

使用 Controller 可以在这里看到:
https://github.com/gngrwzrd/gwpreferences/blob/master/GWPreferences/GWPreferences/GWAppDelegate.m - 您可以在此代码中看到我正在尝试进行一些桥接转换以尝试强制释放对象,但它不起作用。

所以 GWPrefsWindowController.dealloc 方法永远不会被调用。有任何想法吗?

最佳答案

我知道这个问题很老,但对于那些从谷歌来到这里的人来说,答案很简单。

如文档中所述,对于非文档基础应用程序,您可以简单地:

  • 无论您在何处调用 NSWindowController,都请保留它的引用。 (在下面的例子中,它被 myWindowController 引用;
  • 使调用您的 NSWindowController 的类实现协议(protocol) NSWindowDelegate
  • 通过在 windowWillClose: 方法
  • 上将其设置为 nil 来释放您的窗口 Controller

    更准确地回答问题。当惰性实例化您的 Controller 时,将您的类设置为委托(delegate):
    -(IBAction)showMyWindowAction:(id)sender
    {
        // If my window controller is not nil
        if (!myWindowController)
        {
            //instantiate it
            myWindowController = [[MyWindowController alloc] initWithWindowNibName:@"myWindow"];
            // set your class as delegate
            [myWindowController setDelegate:self];
         }
    
         [myWindowController.window orderFront:self];
    }
    

    然后从 windowWillClose: 协议(protocol)中实现 NSWindowDelegate 方法
    -(void)windowWillClose:(NSNotification *)notification
    {
         //Check if it's the right window that will close
         if ([notification.object isEqualTo:myWindowController.window])
         {
             //Set your controller to nil
             myWindowController = nil;
          }
    }
    

    就是这样,您的窗口 Controller 现在将解除分配,并且由于我们在显示窗口之前验证它的 Controller 是否为零,所以一切都会正常进行!

    我相信默认情况下不实现的原因是因为 initWithWindowNibName: 是一个有点繁重的操作,因此您必须考虑取消分配窗口上的任何内容是否会比加载窗口 nib 文件影响更多或更少。

    我希望它有帮助

    关于 cocoa NSWindowController 和 NSWindow 不释放,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20182246/

    10-11 15:16