您是否必须在dealloc中发布IBOulets?

时间:2009-10-07 03:37:42

标签: iphone

您是否必须在dealloc中发布IBOulets?我不确定这个,因为我没有做alloc,通常你只发布你所谓的alloc。有人知道吗?

7 个答案:

答案 0 :(得分:35)

您的IBOutlet可能是@properties。如果是,并且您已将retain作为属性,那么您需要在-dealloc中发布

换句话说:

@interface MyViewController : UIViewController {
    IBOutlet UITableView *myTable;
}

@property (nonatomic, retain) IBOutlet UITableView *myTable;

@end

你的dealloc必须[myTable release];

如果您在Xcode中创建一个新的基于导航的应用程序,并查看appdelegate.h:

@interface Untitled1AppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;
    UINavigationController *navigationController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

@end

和appdelegate.m的dealloc:

- (void)dealloc {
    [navigationController release];
    [window release];
    [super dealloc];
}

这里看到的关键是这样的行:

@property (nonatomic, retain) IBOutlet UIWindow *window;

如果存在保留,则表示该属性由您的代码“拥有”,您必须将其释放。

当然,还有其他方法,例如不将IBOutlets声明为属性,或将其声明为属性而不保留。我发现在大多数情况下,我更喜欢将它们保留为属性,然后我必须明确地释放它们。例如,当您从一个视图控制器切换到另一个视图控制器时。当一个视图控制器被关闭时,其视图将被删除并被释放。如果我没有保留它们,该视图上的任何IBOutlet UILabel也将被释放。这意味着当我回到原来的视图时,我必须通过并将标签和控件重置为最后的值,如果我只保留IBOutlet,我可以轻松保存它们。

答案 1 :(得分:9)

如果您只是在界面中使用IBOutlet,则无需释放它们。原因在于,除非您在代码中明确地保留它们,否则它们只是被设置。他们留下来因为视野在那里。显然,如果您还使用属性并保留它们,则需要在dealloc上发布。

答案 2 :(得分:8)

这不是关于IBOutlet,而是关于你的声明。 如果你在Xcode中使用一个新的项目向导,你可能会在头文件中得到这样的代码。

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;

您可以看到,头文件中有保留关键字。遵循内存管理准则,您必须释放您保留的所有内容(通过调用alloc,copy,retain等)。您在代码中保留,那么您必须发布

此外,该向导已经为您添加了一些发布代码。

- (void)dealloc {
    [tabBarController release];
    [window release];
    [super dealloc];
}

答案 3 :(得分:2)

正如您所说,您应该释放自己分配的所有内容(使用alloccopy)。它以另一种方式工作:你不应该释放你自己没有分配的任何Cocoa对象(一些CoreFoundation函数分配,你负责释放它们,但这不是这里的情况)。

如果您没有分配您的IBOutlet,那么您不必释放它,除非出于某种原因,您将其保留在某处。

答案 4 :(得分:2)

回答Joe D'Andrea提出的问题。您可以使用self.label = nil;。因为它正在调用setLabel,它是自动生成的:

- (void)setLabel:(UILabel *)input
{
   [label autorelease];
   label = [input retain];
}

正如您所看到的,当前label将被释放,然后nil被分配给标签。

但请确保不要将其写为label = nil。那样不行。 因为您需要调用自动生成的标签访问器方法。

答案 5 :(得分:1)

以下是我对IBOutlet个对象(与NIB文件一起)所做的事情:

@interface MyViewController : UIViewController {
  UILabel *label;
}

@property (nonatomic, retain) IBOutlet UILabel *label;

@end

@implementation MyViewController
@synthesize label;

- (void)setView:(UIView *)aView {
  if (!aView) {
    // view is being set to nil
    // set outlets to nil to get the benefit of the didReceiveMemoryWarning!
    self.label = nil;
  }
  // Invoke super's implementation last
  [super setView:aView];
}

- (void)viewDidLoad {
  [super viewDidLoad];
}

- (void)viewDidUnload {
  // Release any retained subviews of the main view.
  // e.g. self.myOutlet = nil;
  self.label = nil;
}

- (void)didReceiveMemoryWarning {
  // Releases the view if it doesn't have a superview.
  [super didReceiveMemoryWarning];

  // Release any cached data, images, etc that aren't in use.
}

- (void)dealloc {
  [label release];
  [super dealloc];
}

附带问题:在dealloc中使用self.label = nil是否更有意义,或者必须release显式调用(例如,为了保持静态分析器的满意度)?

我想,在那一点上,我们还是要走出去,所以没有必要将我的IBOutlet对象设置为nil。

答案 6 :(得分:1)

如果这是你的BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>
@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
}
@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;

@end

然后这将是你在BlahViewController.m中的dealloc

- (void)dealloc
{
    [navigationBar release];
    [super dealloc];
}

但是,如果这是你的BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>
@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
}

@end

然后这将是你在BlahViewController.m中的dealloc

- (void)dealloc
{
    [super dealloc];
}

最后,如果这是你的BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>

@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
    IBOutlet MKMapView *map;
}

@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;

@end

然后这将是你在BlahViewController.m中的dealloc

- (void)dealloc
{
    [navigationBar release];
    [super dealloc];
}

简而言之,如果您使用retain将其声明为属性,则需要将其释放。