关于何时何地释放对象的问题

时间:2010-07-07 12:39:40

标签: iphone memory-management

我有几个地方需要显示警报并以相同的方式处理关闭操作,即将它们带到同一个视图控制器。我没有在所有这些地方复制警报特定代码,而是创建了一个单独的类,如下所示:


AlertUtility.h:
@interface AlertUtility : NSObject {
}
- (void) displayAlert;
@end

AlertUtility.m:
@implementation AlertUtility {
- (void) displayAlert {
   UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:... message:... 
      delegate:self cancelButtonTitle:... otherButtonTitles:nil] autorelease];
   [alert show];
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
   // Create another view controller and display its views
   [self release] // Release current object because I'm not releasing it where I create it
}

}

我需要使用此警报(即在MyViewController中),我有以下内容:


MyViewController.m:
AlertUtility *utility = [[AlertUtility alloc] init];
[utility displayAlert];

正如你所看到的,我不是在这里释放实用程序对象(我应该自己拥有它),而是在AlertUtility类的didDismissWithButtonIndex方法中。我在这里显然遗漏了一些东西。

我已尝试自动释放实用程序对象,但是当实用程序对象上的'did'调用didDismissWithButtonIndex方法时,该对象已经被释放(由于自动释放)。

我尝试将displayAlert方法设为静态(并使用[AlertUtility displayAlert];调用它),但是从不调用didDismissWithButtonIndex。

我应该像在现在一样从didDismissWithButtonIndex方法中释放当前对象,还是有办法在MyViewController中释放它(不为当前类创建AlertUtility属性)?

谢谢!

修改 我应该使用Singleton模式吗?

3 个答案:

答案 0 :(得分:1)

调用[self release]是一个很大的禁忌,因为没有对象有关于其他对象引用它的信息。保留系统旨在确保如果ObjA需要ObjB,ObjB将保留在内存中,直到ObjA不再需要它为止。如果ObjB自行释放,整个系统就会崩溃。

在这种情况下,UIAlert本身会保留AlertUtility对象作为其委托,这样您就可以在完成AlertUtility时尽快释放UIAlert AlertUtility *utility = [[AlertUtility alloc] init]; [utility displayAlert]; [utility release]; // released here, but still alive }}

所以,这很好:

AlertUtility

如果init对象在发布之后仍然存在,那么这不是问题。发布不一定会杀死对象。它只是说发送释放消息的对象不再需要释放的对象。每个保留对象都有责任平衡所有保留(包括AlertUtility等隐式保留)与发布。过去保留对象对系统是否保持释放对象不活动没有兴趣也不负责任。

毕竟,任何单个对象都可以由多个保留对象保留,每个对象都不知道另一个对象。在这种情况下,init由ViewController与UIAlert保留一次。 然后由AlertUtility作为代理再次保留。编辑: UIAlert为其委派代理当ViewController时释放UIAlert对象,只要UIAlert需要它就会保持活动状态,反之亦然。

由于UIWindow对象在显示时保留AlertUtility,这意味着UIAlert对象将保持活动状态,直到UIAlert被解除为止。(编辑:这仅对视图有效,而不是AlertUtility委托)

你通常不会有一个UIAlert委托,其存在完全取决于UIAlert本身的委托。通常,{{1}}委托是视图唤起警报的控制器。这样,在完成与警报关联的任务之前,您不必担心委托人死亡。

答案 1 :(得分:0)

你的模式有效,虽然我同意在其他地方发布它是丑陋的,我试图避免这种情况。您可以采取以下方法:

// AlertUtility.h:
@interface AlertUtility : NSObject {
}
- (void) displayAlert;
@end

// AlertUtility.m:
@implementation AlertUtility {
- (void) displayAlert {
   UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:... message:... 
      delegate:self cancelButtonTitle:... otherButtonTitles:nil] autorelease];
   [alert show];
   [self retain];   // explicitly retain this (self) object
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
   // Create another view controller and display its views
   [self release] // Release current object because you retained it earlier here
}

}

后来:

 // MyViewController.m:
    AlertUtility *utility = [[AlertUtility alloc] init];
    [utility displayAlert];
    [utility release];   // released here, but still alive

编辑:删除了警报上的版本,因为它是自动释放的。

答案 2 :(得分:0)

您可以改用:

void displayAlert(NSString *title, NSString *message)
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
        message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

或者只是:

#define MY_ALERT(TITLE, MESSAGE) \
[[[[UIAlertView alloc] initWithTitle:TITLE \
                             message:MESSAGE \
                            delegate:nil \
                   cancelButtonTitle:@"OK" \
                   otherButtonTitles:nil] autorelease] show]

然后写:

MY_ALERT(nil, @"Press, OK!");