【问题标题】:ObjC: How to proper implement a class that release itself?ObjC:如何正确实现一个释放自己的类?
【发布时间】:2011-06-04 00:43:40
【问题描述】:

我正在实现一个登录视图,我需要在我的应用程序中随时显示此视图。因此,为了更容易,我创建了一个名为 showLogin 的类方法,当视图关闭时,我希望它自行释放,所以我这样做了:

@implementation LoginController

@synthesize releaseOnClose;

+ (void)showLogin {
     LoginController *login = [[LoginController alloc] init];
     login.releaseOnClose = YES;
     [login show]; // Potential leak of login object
}

- (id)init {
     if (self = [super initWithNibName:@"Login" bundle:[NSBundle mainBundle]]) {
          releaseOnClose = NO;
     }
     return self;
}



- (void)show {
     if (self.view.superview == nil) {
          // show the view
     }
}



- (void)btnCloseTouched {
     [self.view removeFromSuperview];
     if (releaseOnClose) {
          [self release];
     }
}

静态分析器告诉我 showLogin 可能存在泄漏,但实际上没有,因为我在 btnCloseTouched 中释放了对象(不要担心登录视图的其他功能,现在它只是打开并关闭)。

所以我想知道如何避免这种潜在的泄漏消息以及如何正确实现这种 if 类方法来正确处理内存?

理念

更多关于我的想法。我想调用 showLogin,它会一直存在,直到它关闭,而调用者不必管理实例。

【问题讨论】:

    标签: objective-c xcode ios memory-management


    【解决方案1】:

    它抱怨泄漏的原因是因为您正在分配未释放的内存 - 例如:

    LoginController *login = [[LoginController alloc] init];
    

    你这样做的方式似乎完全倒退了——不太清楚为什么你要在其自身内部实例化一个新的 LoginController 对象,然后释放 self 以尝试释放新对象?必须有更好的方法。

    您必须释放您分配的实例 - self 不是您分配的新实例(登录)。

    完成后请执行以下操作:

    [login release];
    

    【讨论】:

    • 我没有得到第二部分。 btmCloseTouched 中的 self 是正确的实例。不过,同意其他部分。
    • self != LoginController *login = [[LoginController alloc] init];尽管。它可能是包含“登录”的对象的正确实例,但它不是同一个实例。无论如何,代码确实令人困惑 - 它有缺陷。
    • @xil3 看起来类方法告诉实例显示,然后实例接收关闭(和释放)的操作。这肯定很奇怪,但似乎可行。
    • @Richard 是的,它释放了自己,但是它为其分配内存的新登录对象没有被释放。我明白你在说什么——登录对象是同一个类的一个新实例,它应该反过来释放自己。我想它有可能会起作用,但它很容易失败。有很多更简单的方法可以做到这一点。
    • @xil3 +showLogin 在这里就像一个工厂;它是一个类方法,所以唯一的LoginWindow 对象是接收btnCloseTouched 消息并自行释放的对象。但同样,有更简单的方法可以做到这一点。
    【解决方案2】:

    在您的@implementation 块中,您可以像这样声明 LoginController 类:

    @implementation LoginController
    
    @synthesize releaseOnClose;
    
    LoginController *mySingleLoginController;
    

    然后在你的类方法中你可以这样做:

    + (void)showLogin {
         mySingleLoginController = [[LoginController alloc] init];
    ...
    

    但是作为一种设计选择,我不推荐这种方法...

    莫西

    【讨论】:

      【解决方案3】:

      为什么不为登录窗口 (LoginView) 创建一个新类,然后确保该类在 dealloc 中自行清理。然后,您可以在需要时创建该类的新实例,并且在删除它时应该没有内存泄漏。

      【讨论】:

      • 我不确定我是否得到你的建议,但我认为这不是问题所在。所有的 dealloc 都可以,分析器告诉你存在潜在的泄漏,因为按照惯例,每个 alloc 都需要一个释放,并且它找不到释放(在 btnCloseTouched 中)。我不确定我是否正确实现了这种类。
      • 我的意思是你应该为登录窗口创建一个单独的类,然后当你需要显示它时,创建一个实例,将它添加到你的视图中,然后释放它。当您从视图中删除它时,它的内存将在dealloc 中得到处理。这似乎是一种更常规的方式。
      【解决方案4】:

      为什么不按普通方式做,让初始化类的实例释放它,或者放到自动释放池中?

      我看不出有一个类在某些操作发生时删除和释放自身的好处。你这样做的动机是什么?

      【讨论】:

      • 我正在考虑简化事情,但我正在改变主意,因为其他人说这容易出错。
      猜你喜欢
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多