您是否必须在dealloc中发布IBOulets?我不确定这个,因为我没有做alloc,通常你只发布你所谓的alloc。有人知道吗?
答案 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)
正如您所说,您应该释放自己分配的所有内容(使用alloc
或copy
)。它以另一种方式工作:你不应该释放你自己没有分配的任何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
将其声明为属性,则需要将其释放。