非模态 Windows 内存管理

2023-12-30

我是 Mac 开发新手。我来自 iPhone 开发人员。 我的问题涉及非模式窗口管理。它与iPhone及其内存管理模型有很大不同。

举例来说,我有一个首选项窗口,我可以使用类似的东西来显示该窗口:

-(IBAction)showPreferenceController:(id)sender {
  if (!preferenceController) {
  preferenceController = [[PreferenceController alloc]init];
  }
  [preferenceController showWindow:preferenceController]; 
}

但使用此代码,该窗口将在应用程序生命周期中保留在内存中,因为该窗口永远不会被释放。

为了避免这种情况,我还可以使用此处描述的方法:
stackoverflow.com/questions/1391260/who-owns-an-nswindowcontroller-in-standard-practice
创建于PreferenceController a + (id) sharedInstance并使用释放窗口(void)windowWillClose:(NSNotification *)notification

我看到许多可可代码示例,其中非模式窗口从未被释放。 例如这里:http://www.mattballdesign.com/blog/2008/10/01/building-a-preferences-window/ http://www.mattballdesign.com/blog/2008/10/01/building-a-preferences-window/:首选项面板和所有子视图均在中创建awakeFromNib因此在应用程序的整个生命周期中都将存在于内存中。

如果以 Xcode 应用程序为例,有很多非模式窗口:
- 全局查找窗口(CMD+MAJ+F)
- 应用程序信息面板
- 帮助窗口
- ...

我认为这些窗口在关闭时会被释放,以保持尽可能低的内存。 我想要一些建议来了解在可可应用程序中管理非模式窗口的最佳方法。 保留在记忆中吗?尽快释放? 我知道与 iPhone 相比,Mac 拥有大量内存,但我也认为保留我们不使用的内存对象并不好。

Thanks.

与 Rob 帖子一起编辑 :

我将 -autorelease 发送到窗口并将指针设置为 nil,以便稍后重新创建窗口。这与您引用的技术类似,尽管是否为控制器使用 +sharedController 并不相关;无论您是否有共享控制器,您都可以执行此操作。

如果没有单例(+sharedController),我不知道如何做到这一点。
我用这个例子解释我的意思:
在应用程序控制器中:

@interface AppController : NSObject <NSApplicationDelegate> {

执行 :

-(IBAction)showPreferenceController:(id)sender {  
  if (!preferenceController) {
    preferenceController = [[PreferenceController alloc]init];
  }
  [preferenceController showWindow:preferenceController];
}  

在首选项控制器中:

@interface PreferenceController : NSWindowController <NSWindowDelegate>

执行 :

- (void)windowWillClose:(NSNotification *)notification {
  [self autorelease];self=nil;
}

当我关闭窗口并在窗口后重新打开时,它会崩溃:preferenceController被释放但不等于nil。所以我需要在窗口关闭时将preferenceController设置为nil。 对于单例来说这样做没有问题。
如果没有单例,我应该将 appController 设置为首选项窗口的委托,以便能够在窗口关闭时将首选项控制器设置为 nil。但我不喜欢这样。

编辑普雷斯顿评论
我没有这么说,但我只想要我的非模态窗口的一个实例,即使我们调用-(IBAction)showPreferenceController:(id)sender几次。
这就是为什么我测试appController中的preferenceController是否等于nil。
因此,如果我们关闭窗口,我需要在 appController 中将preferenceController 设置为 nil。
所以解决方案是:
在应用程序控制器中,监听 NSWindowWillCloseNotification:

- (void)windowWillClose:(NSNotification *)notification {
    if ([notification object] == [preferenceController window]) {
        [preferenceController autorelease];
        preferenceController = nil;
    }
}

这是对的吗?这是唯一的解决方案吗?因为管理我的非模态窗口似乎有点复杂......


你在这里的思考方式都是正确的。仅仅因为内存很多就泄漏内存是不行的。也就是说,仅仅因为 Windows 在 Mac 上关闭而不释放它们是很常见的。如果您认为它们将再次打开,您通常应该保留它们以避免重新加载它们的成本。

有两种思想流派NSWindow:拥有的和无拥有的。我属于“拥有”思想流派。我通常给每个窗口一个所有者,用 ivar 保留它并在适当的时候释放它。通常这是委托,有时是应用程序控制器。在-windowShouldClose:,我发送-autorelease到窗口并将指针设置为零,以便稍后重新创建窗口。这与您引用的技术类似,尽管是否使用+sharedController因为控制器不相关;无论您是否有共享控制器,您都可以执行此操作。

无主学派的思想是使用 NSWindow 的-setReleasedWhenClosed:以便它在关闭时自动释放。我相信您引用的几个窗口在系统提供时都会这样做,因为可能没有委托。这在某些类型的面板中可能很有用,但我会小心地将其作为一般模式。几乎在所有情况下最好都进行显式内存管理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

非模态 Windows 内存管理 的相关文章

随机推荐