非模态窗口内存管理 [英] Non-modal windows memory management

查看:97
本文介绍了非模态窗口内存管理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Mac Dev的新手。我来自iPhone开发。
我的问题与非模态窗口管理有关。它与iPhone和它的内存管理模型有很大的不同。



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

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

但是使用这个代码,窗口将在应用程序生命期间保留在内存中,因为窗口永远不会释放。



为了避免这种情况,我也可以使用这里描述的方法:

stackoverflow.com/questions/1391260/who-

中创建PreferenceController a +(id)sharedInstance 并使用(void)windowWillClose:(NSNotification *)notification



代码样本,其中非模态窗口从不释放。
例如: http:/ /www.mattballdesign.com/blog/2008/10/01/building-a-preferences-window/ :偏好面板和所有子视图都在 awakeFromNib

如果你以Xcode应用程序为例,有很多非模态窗口:

- 全局查找窗口(CMD + MAJ + F)

- 应用信息面板

- 帮助窗口

- ...



我想这些窗口被释放时,它们关闭以保持内存尽可能低。
我想一些建议知道在可可应用程序中管理非模态窗口的最佳方式。
保存在内存中?发布asap?
我知道一个mac有一个很大的内存相比,一个iPhone,但我也认为这是不好的保存在我们不使用的内存对象。



感谢。



使用Rob post编辑


我发送-autorelease到窗口,并将我的指针设置为nil,所以我将重新创建窗口。这是类似于你引用的技术,虽然是否使用+ sharedController的Controller是不相关的;


我不知道如何做到没有单例(+ sharedController )。

我用这个例子解释我的意思:

在应用程序控制器中:

  @interface AppController:NSObject< NSApplicationDelegate>实施:

 {


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

在偏好控制器中:

  @interface PreferenceController:NSWindowController< NSWindowDelegate>实施:

  

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

当我关闭并重新打开窗口后会崩溃:preferenceController被释放,不等于nil。所以我需要设置preferenceController为nil当窗口关闭。
使用单例操作没有问题。

没有单例,我应该将appController设置为偏好窗口的委托,以便在窗口关闭时将preferenceController设置为nil。

使用Preston编辑的评论

我没有说,但我只需要一个非模态窗口的实例,即使我们调用 - (IBAction)showPreferenceController:(id)sender 多次。

这就是为什么我测试ifController在appController中是否等于nil。

所以,如果我们关闭窗口,我需要在appController中将preferenceController设置为nil。

所以解决方案是: br>
在AppController 中,侦听NSWindowWillCloseNotification:

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

是否正确?这是唯一的解决方案吗?因为看起来有点复杂,只是为了管理我的非模态窗口...

解决方案

方法。它不是确定泄漏记忆只是因为你有很多。也就是说,通常不是因为它们在Mac上关闭而释放窗口。



如果你认为他们将要再次开放,你应该坚持下去。 $ c> NSWindow :拥有和未拥有。我是拥有的思想学派。我通常给每个窗口的所有者保留它与ivar并释放它在适当的时候。通常这是委托,有时它是应用程序控制器。在 -windowShouldClose:,我发送 -autorelease 到窗口,并将我的指针设置为nil,所以我将重新创建窗口。这与你引用的技术类似,不过是否使用 + sharedController 为Controller不相关;



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


I'm a newbie in Mac Dev. I come from iPhone dev. My question relates to non-modal windows management. It's quite different from the iPhone and it's memory management model.

Say for example, i have a preference window, i can use something like that to show the window:

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

But with this code, the window will stay in memory during app life because the window is never released.

To avoid that, I could also use the method described here :
stackoverflow.com/questions/1391260/who-owns-an-nswindowcontroller-in-standard-practice
Create in PreferenceController a + (id) sharedInstance and release the window using (void)windowWillClose:(NSNotification *)notification

I see many cocoa code samples where non-modal windows are never released. For example here : http://www.mattballdesign.com/blog/2008/10/01/building-a-preferences-window/ : The preference panel and all the subviews are created in awakeFromNib and so will live in memory during all app life.

If you take for example Xcode app, there are a lot of non-modal windows :
- Global Find window (CMD+MAJ+F)
- App Info Panel
- Help Window
- ...

I suppose that these windows are released when they are closed to keep memory as low as possible. I would like some advices to know the best way to manage non-modal windows in a cocoa app. Keep in memory? Releasing asap? I know a mac has a lot of memory compared to an iPhone but I also think it's not good to keep in memory objects we are not using.

Thanks.

Edited with Rob post :

I send -autorelease to the window and set my pointer to nil so I'll recreate the window later. This is similar to the technique you cite, though whether or not to use +sharedController for the Controller isn't related; you can do this whether you have a shared controller or not.

I don't how to do that without a singleton (+sharedController).
I explain what I mean with this example:
In the app Controller :

@interface AppController : NSObject <NSApplicationDelegate> {

Implementation :

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

In the preferences controller :

@interface PreferenceController : NSWindowController <NSWindowDelegate>

Implementation :

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

It will crash when i close and reopen after the window : preferenceController is released but not equal to nil. So I need to set preferenceController to nil when the window is closed. There is no problem to do that with a singleton.
Without singleton, I should set appController as the delegate of Preference Window to be able to set preferenceController to nil when the window is closed. But i don't like that way.

Edited with Preston comments
I didn't say it but I want only one instance of my non-modal window even if we call -(IBAction)showPreferenceController:(id)sender several times.
That's why I test if preferenceController is equal to nil or not in appController.
So, I need to set preferenceController to nil in appController if we close the window.
So the solution would be :
In AppController, listening NSWindowWillCloseNotification:

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

Is it correct? Is this the only one solution? because it seems a little bit complicated just to manage my non modal window...

解决方案

You're thinking in all the right ways here. It's not ok to leak memory just because you have a lot of it. That said, it is common not to release windows just because they close on Mac. You should generally hold onto them if you think they're going to be opened again to avoid the cost of reloading them.

There are two schools of thought on NSWindow: owned and unowned. I am of the "owned" school of thought. I generally give every window an owner that retains it with an ivar and releases it when appropriate. Generally that is the delegate, sometimes it's the app controller. In -windowShouldClose:, I send -autorelease to the window and set my pointer to nil so I'll recreate the window later. This is similar to the technique you cite, though whether or not to use +sharedController for the Controller isn't related; you can do this whether you have a shared controller or not.

The unowned school of thought is to use NSWindow's -setReleasedWhenClosed: so that it automatically releases itself when it closes. I believe several of the windows you reference do it this way when they are provided by the system, since there might not be a delegate. This can be useful in certain kinds of panels, but I would be careful with it as a general pattern. It's better to have explicit memory management in almost all cases.

这篇关于非模态窗口内存管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆