使用手动内存管理。以下代码运行良好,不会发生崩溃。但是没有-(void)dealloc
方法。这段代码有错吗?我应该添加-(void)dealloc
吗?
MyClass.h
#import <UIKit/UIKit.h>
@interface MyClass : NSObject {
@private
BOOL flag;
UIView *view;
UILabel *label;
UIButton *button;
UITabBar *tabBar;
UIWebView *webView;
UIImageView *imageView;
}
@property (nonatomic, retain) UIView *view;
@property (nonatomic, retain) UILabel *label;
@property (nonatomic, retain) UIButton *button;
@property (nonatomic, retain) UITabBar *tabBar;
@property (nonatomic, retain) UIWebView *webView;
@end
我的班级
#import "MyClass.h"
@implementation MyClass
@synthesize view;
@synthesize label;
@synthesize button;
@synthesize tabBar;
@synthesize webView;
- (id)init {
self = [super init];
if (self) {
// Initialization code
// Among other code,
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
}
return self;
}
// Other methods here.
// But -(void)dealloc is not overridden here in the MyClass.m
@end
如果我们必须为上面的代码添加-(void)dealloc
,它应该是这样的:
被覆盖 -(无效)交易
-(void)dealloc {
[view release];
[label release];
[button release];
[tabBar release];
[webView release];
[super dealloc];
}
更新 1
@synthesize添加,见上文。
更新 2
没有把它放到另一篇文章中,因为这似乎是相当相关的问题:
看到上面的MyClass.m/.h
,有一个私有的ivar(不确定这里应该叫ivar或field)UIImageView *imageView;
,它没有属性,没有@synthesize
,初始化在那里给出,我们怎么解散它?还[imageView release];
-(void)dealloc
?
更新 3
在发布ivar之前,我们必须检查可用性吗?也就是说,而不是 [view release];
,使用这个:
if (nil != view) {
[view release];
}
是的。您需要实现 dealloc。
您的交易位置将如下所示:
-(void)dealloc {
[_view release];
[_label release];
[_button release];
[_tabBar release];
[_webView release];
[super dealloc];
}
任何保留/复制的属性都应在 dealloc 上释放。
你的iVar没有任何意义。它们与属性的信息不同,因此您可以删除 iVar。
如果您希望您的属性由您的 iVar 备份,您应该像这样@synthesize
它们:
@synthesize view = view;
@synthesize label = label;
@synthesize button = button;
@synthesize tabBar = tabBar;
@synthesize webView = webView;
由于您没有使用 ARC,因此您的代码(包括 dealloc 方法)是正确的,但是您在实现中缺少 @synthesize 语句以使属性正常工作:
@implementation MyClass
// this will synthesize the getters and setters
@synthesize view, label, button, tabBar, webView;
- (id)init {
self = [super init];
if (self) {
// Initialization code
}
return self;
}
// Other methods here.
-(void)dealloc {
[view release];
[label release];
[button release];
[tabBar release];
[webView release];
[super dealloc];
}
@end
虽然丹尼尔的回答在回答你的问题时是正确的,但它并没有涵盖你应该做什么。
这就是在现代世界中编写代码的方式:
-
打开 ARC。 特别是如果您正在学习或这是您的第一个项目。 没有理由不使用 ARC。 学习手动保留发布很有价值,但目前并不重要,因为这些工具在分析基于 ARC 的模式何时泄漏内存方面做得很好(分析器或使用仪器,两者都需要在 MRR 下使用,而在 MRR 下两者都不能很好地工作)。
不要使用 @synthesize,也不要声明 iVars (当然也不要在 .h 文件中声明 iVars)。 让编译器自动合成
_
前缀的 ivar。_
前缀的另一个优点是不允许你意外地直接访问代码中的 ivar。 即self.foo
vs.foo
; 第二个不会编译。
或者翻译成代码:
@interface MyClass : NSObject
@property (nonatomic, retain) UIView *view;
@property (nonatomic, retain) UILabel *label;
@property (nonatomic, retain) UIButton *button;
@property (nonatomic, retain) UITabBar *tabBar;
@property (nonatomic, retain) UIWebView *webView;
@end
和:
@implementation MyClass
{
BOOL _flag;
UIImageView *_imageView;
}
- (id)init {
self = [super init];
if (self) {
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
}
return self;
}
// no -dealloc
@end
请注意,我将 _imageView
声明为一个实例变量,如果您稍后需要重构类以使其在外部可用,该变量将与明显的imageView
@property
兼容。
如果您确实必须使用手动保留-释放,则添加一个在所有 ivar 上调用 -release
的-dealloc
方法。 即[_view release];
、[_imageView release];
等...
不明白你的意思是"请注意,我宣布_imageView为 将与明显的图像兼容的实例变量查看 @property以后是否需要重构类才能做到这一点 外部可用。
如果您决定其他对象需要访问_imageView
,则可以删除 iVar 声明并添加:
@property(nonatomic, retain) UIImageView *imageView;
编译器自动合成将自动创建一个名为 _imageView
的实例变量,其余代码都不必更改。
我们是否必须确保 ivar 不是零,然后再将其释放到 交易方法?(请参阅上面的更新 3。
不。 在 Objective-C 中,nil 吃消息。 也就是说,[nil release];
是完全有效的,并且在运行时绝对不执行任何操作。
在您的代码中,BOOL 标志 ; 已消失。我们是否做了一个 布尔标志的属性;,即@property布尔标志;?或者我们所拥有的一切 只需在MyClass.h中放置一个私有字段作为@private 布尔旗;在我最初的问题中?
我忘了。 您可以为其创建一个属性。 或者你可以像我上面所做的那样,在_imageView
旁边将_flag
声明为 iVar。
最重要的是,不再有任何理由(除了通常避免的极少数情况)在.h中声明实例变量。