如何处理自定义模式对话框设置/拆卸的内存管理

时间:2011-01-23 23:41:43

标签: objective-c memory-management

目前我的应用程序在等待Web服务时使用自定义模式对话框对象

@implementation AddModalDialog

- (void)buildModalDialogWithTextForView:(NSString *)text:(UIViewController *)controller
{
  UIView* _hudView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 400, 450)];
  _hudView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
  _hudView.clipsToBounds = YES;

  UIActivityIndicatorView* _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
  _activityIndicatorView.frame = CGRectMake(140, 135, _activityIndicatorView.bounds.size.width, _activityIndicatorView.bounds.size.height);
  [_hudView addSubview:_activityIndicatorView];
  [_activityIndicatorView startAnimating];

  UILabel* _captionLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, 190, 250, 22)];
  _captionLabel.backgroundColor = [UIColor clearColor];
  _captionLabel.textColor = [UIColor whiteColor];
  _captionLabel.font = [UIFont systemFontOfSize:13.0];
  _captionLabel.adjustsFontSizeToFitWidth = NO;
  _captionLabel.textAlignment = UITextAlignmentCenter;
  _captionLabel.text = text;
  [_hudView addSubview:_captionLabel];

  [controller.view addSubview:_hudView];
}

- (void)removeModalDialogForView:(UIViewController *)controller
{
  NSUInteger i, count = [controller.view.subviews count];
  [[controller.view.subviews objectAtIndex:(count - 1)] removeFromSuperview];
}

@end

我的问题与使用此对象时的内存管理有关。你可能会注意到上面的自定义UIView中的任何内容都是受欢迎的,因为它有改进的余地我确定。

当我想要提取模态

时,以下是我目前在其他对象中的工作方式
- (void)viewDidLoad
{
  AddModalDialog* modal = [[AddModalDialog alloc] init];
  [modal buildModalDialogWithTextForView:@"Loading some details ..." :self];
  [modal release];
}

然后,在完成Web服务之后,我通常会将其拆除

- (void)returnWebServiceDetails:(MyClass *)obj
{ 
  AddModalDialog* modal = [[AddModalDialog alloc] init];
  [modal removeModalDialogForView:self];
  [modal release];
}

我不应该两次初始化此对象而是拥有属性吗?新的obj-c开发人员正在寻找围绕此行为的最佳实践。

提前谢谢

2 个答案:

答案 0 :(得分:2)

buildModalDialogWithTextForView底部,在_activityIndicatorView_captionLabel_hudView上发布 - 您是这些人的所有者(通过创建它们)。否则,它们就会泄漏。

有关Object Ownership and Disposal和CoreFoundation Ownership Policy

的更多信息

答案 1 :(得分:2)

首先,您有效地将这些项目的所有权转移到控制器的视图中(因为您没有对它们进行任何引用),因此您应该在将它们添加到控制器的子视图后将它们全部释放。

其次,不应该假设您知道控制器视图层次结构的结构,而应该使用希望与应用程序中的任何其他内容不冲突的内容标记_hudView,并使用它来检索您的视图。

第三,既然你根本没有引用,那么这些作为类方法而不是实例会更好。没有必要创建这个对象的实例只是为了让它添加一些视图并消失。

因此,遵循这三条准则的相同代码可能如下所示:

@interface AddModalDialog {
}

+ (void)buildModalDialogWithText:(NSString *)text forController:(UIViewController *)controller;
+ (void)removeModalDialogForController:(UIViewController *)controller;

@end

@implementation AddModalDialog

// Class methods: use '+' instead of '-'
+ (void)buildModalDialogWithText:(NSString *)text forController:(UIViewController *)controller
{
  UIView* _hudView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 400, 450)];
  _hudView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
  _hudView.clipsToBounds = YES;
  _hudView.tag = 2000; // use something that won't clash with tags you may already use

  UIActivityIndicatorView* _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
  _activityIndicatorView.frame = CGRectMake(140, 135, _activityIndicatorView.bounds.size.width, _activityIndicatorView.bounds.size.height);
  [_hudView addSubview:_activityIndicatorView];
  [_activityIndicatorView startAnimating];
  [_activityIndicatorView release]; // _hudView owns this now

  UILabel* _captionLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, 190, 250, 22)];
  _captionLabel.backgroundColor = [UIColor clearColor];
  _captionLabel.textColor = [UIColor whiteColor];
  _captionLabel.font = [UIFont systemFontOfSize:13.0];
  _captionLabel.adjustsFontSizeToFitWidth = NO;
  _captionLabel.textAlignment = UITextAlignmentCenter;
  _captionLabel.text = text;
  [_hudView addSubview:_captionLabel];
  [_captionLabel release]; // _hudView owns this now

  [controller.view addSubview:_hudView];
  [_hudView release]; // the controller's view owns this now
}

// Class methods: use '+' instead of '-'
+ (void)removeModalDialogForController:(UIViewController *)controller
{
  UIView* _hudView = [controller.view viewWithTag:2000];
  [_hudView removeFromSuperView]; // owned by the view, so we don't need to do anything more
}

@end

你会用它:

- (void)viewDidLoad
{
  // Class methods, so we don't need to create an instance to use
  [AddModalDialog buildModalDialogWithText:@"Loading some details..." forController:self];
}

- (void)returnWebServiceDetails:(id)obj
{
  // Class methods, so we don't need to create an instance to use
  [AddModalDialog removeModalDialogForController:self];
}