Cocoa NSWindowController和NSWindow Not Deallocing

时间:2013-11-24 23:01:29

标签: cocoa release nswindow dealloc nswindowcontroller

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

Apple的文档:

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:method中找到解释“实现”内容的任何地方。

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

在这里可以看到使用控制器: https://github.com/gngrwzrd/gwpreferences/blob/master/GWPreferences/GWPreferences/GWAppDelegate.m - 您可以在此代码中看到我正在尝试使用某种桥接器来尝试强制释放对象,但它不起作用。

因此永远不会调用GWPrefsWindowController.dealloc方法。有什么想法吗?

1 个答案:

答案 0 :(得分:5)

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

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

  • 在您呼叫它的任何地方为NSWindowController保留参考。 (在下面的示例中,myWindowController引用了它;
  • 让课程调用您的NSWindowController实施协议NSWindowDelegate;
  • 通过windowWillClose:方法
  • 将其设置为nil来释放您的Window Controller

更准确地回答这个问题。在延迟实例化控制器时,将您的类设置为委托:

-(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:协议

实施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;
      }
}

就是这样,你的窗口控制器现在会被释放,因为我们在显示窗口之前验证它的控制器是否为零,一切都会正常工作!

我认为默认情况下没有实现这一点的原因是因为initWithWindowNibName:是一个有点繁重的操作,因此你必须考虑你窗口上的任何内容是否会影响或多或少而不是加载你的窗口nib文件。

我希望它有所帮助