【发布时间】:2009-10-07 03:37:42
【问题描述】:
你必须在 dealloc 中释放 IBoulet 吗?我不确定这个,因为我没有做分配,通常你只为你调用 alloc 的东西释放。有人知道吗?
【问题讨论】:
标签: iphone
你必须在 dealloc 中释放 IBoulet 吗?我不确定这个,因为我没有做分配,通常你只为你调用 alloc 的东西释放。有人知道吗?
【问题讨论】:
标签: iphone
您的 IBOutlets 可能是 @properties。如果是,并且您有retain 作为属性,那么您确实需要在-dealloc 中释放
换句话说:
@interface MyViewController : UIViewController {
IBOutlet UITableView *myTable;
}
@property (nonatomic, retain) IBOutlet UITableView *myTable;
@end
你必须在你的交易中[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,我可以很容易地保存它们。
【讨论】:
如果您只是在界面中使用 IBOutlet,则不需要释放它们。原因是除非您在代码中明确保留它们,否则它们只是被设置。他们留下来是因为那里有风景。显然,如果你还使用属性并保留它们,则需要在 dealloc 上释放。
【讨论】:
这不是关于 IBOutlet,而是关于你的声明。 如果您在 Xcode 中使用新项目向导,您可能会在头文件中得到一些类似这样的代码。
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
可以看到,头文件中有retain关键字。遵循内存管理指南,您必须释放您保留的所有内容(通过调用 alloc、复制、保留等)。而且您的代码中有retain,那么您必须release它。
此外,向导已经为您添加了一些发布代码。
- (void)dealloc {
[tabBarController release];
[window release];
[super dealloc];
}
【讨论】:
正如您所说,您应该释放自己分配的所有内容(使用alloc 或copy)。它以另一种方式工作:你不应该释放任何不是你自己分配的 Cocoa 对象(一些 CoreFoundation 函数分配,你负责释放它们,但这里不是这种情况)。
如果您没有分配您的 IBOutlet,那么您不必释放它,当然,除非出于某种原因,您将它保留在某个地方。
【讨论】:
回答 Joe D'Andrea 的附带问题。您可以使用self.label = nil;。因为它调用的是自动生成的setLabel:
- (void)setLabel:(UILabel *)input
{
[label autorelease];
label = [input retain];
}
如您所见,当前的label 将被释放,然后nil 被分配给标签。
但请确保不要将其写为label = nil。这是行不通的。
因为您需要调用自动生成的标签访问器方法。
【讨论】:
以下是我对 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。
【讨论】:
如果这是你的 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,那么你需要释放它。
【讨论】: