我是iPhone编程的新手。我有以下疑问阻止我继续前进。请考虑以下代码:
---------.h------
@interface myClass: UIViewController
{
UIImage *temp;
}
@property (nonatomic, retain) UIImage *temp;
---------.m------
@interface myClass
@synthesize temp;
-(void) dealloc
{
[temp release];
[super dealloc];
}
以上是唯一的程序代码。多数民众赞成......没有别的。我是否需要在dealloc方法中声明[temp release],即使我根本没有在我的程序中使用属性访问器方法。如果我没有在dealloc中声明[temp release]怎么办?这会造成内存泄漏,因为我发布了一些我没有保留的东西,因为我没有调用属性访问器方法。
此外,当我为temp打印保留计数时,为什么它显示为0,即使它保留在@property中。
提前致谢
答案 0 :(得分:1)
如果没有为myClass.temp(的一个实例)分配任何值,那么就不会有泄漏。但是你应该在你的dealloc中发布它。
@property只是一个声明,myClass的实例将具有此属性。您需要在保留该值之前为其分配值。
myClass *instance = [[myClass alloc] init];
// instance will now retain the value passed in
// and is therefore responsible for releasing it
instance.temp = [UIImage imageNamed:@"whatever"];
// if instance is not retained anywhere else,
// its dealloc will be called
[instance release];
在旁注中,您应该为您的类命名以大写字母开头
信,即MyClass
。不是必需的,但让事情更清楚。
你也可以在你的self.temp = nil;
中使用dealloc
你不应该这样,但它有点好用,看起来更干净。这是一个不确定的主题......
答案 1 :(得分:0)
你在做什么是正确的。滚动到此Apple Doc的“dealloc”部分:Declared Properties
然而,很快,这些属性将在您合成它们时自动清理(在下一个Cocoa更新中) - 也就是说,我个人开始遵循的惯例,以便我的代码将来工作正在设置{ {1}}在dealloc而不是发送一条发布消息(阅读我发布的苹果文档,它解释了这一点)。在运行时创建的访问器方法首先释放对象,因此对于我和其他一些开发人员来说,这是一种更好/更安全的方法来清理dealloc中声明的属性。
答案 2 :(得分:0)
您的代码是正确的。
一般规则是,对于在@interface中声明的所有变量,必须在-dealloc
中清除它们。一些变量需要被释放,其他变量只需要被取消,这取决于你如何声明@property。
在上面的示例中, temp 可能永远不会被您明确赋值,但是当一个实例时,ObjC运行时会将 temp 的值初始化为nil你的班级被分配了。
将 -release 发送到nil对象通常不是问题,因此[temp release]
很好。这是一个无操作。当 temp 在-dealloc,
中具有非零值时,[temp release]
可以完成释放内存的工作。
如果您需要 temp 在创建时具有非零值,则需要实现-init
方法并确保它获得某些值。虽然你的课程是合法的,但是没有-init
方法的功能,你真的应该养成习惯,包括你设计的每个自定义类中的一个。
您至少需要默认初始值设定项:-init
。您可能还想设计一个更详细的初始化程序,可用于为您的 temp ivar提供一个值,例如-initWithImage:
以下是您在课堂上应该包括的内容:
@implementation MyClass
...
- (id) init {
self = [super init];
if (self != nil) {
// The minimal default initializer.
// temp will already have a value of nil, so you don't need necessarily
// need to do anything more, unless temp needs a real value on initialization.
}
return self;
}
- (void) dealloc {
...
}
@end
要实现更详细的初始值设定项(称为指定的初始值设定项),您可能会这样:
@implementation MyClass
...
- (id) initWithImage:(UIImage *)newImage {
self = [super init];
if (self != nil) {
temp = [newImage retain];
}
return self;
}
// Implement the default initializer using your more detailed initializer.
- (id) init {
// In this default initializer, every new instance comes with a temp image!
return [self initWithImage:[UIImage imageNamed:@"foobar"]];
}
- (void) dealloc {
...
}
@end
此处,指定的初始值设定项-initWithImage:
是权威初始值设定项。所有其他初始值设定项(包括-init
)均使用-initWithImage:
实现。
对于是否在最小默认初始化程序之外实现任何初始值设定项,您可以自行决定。也许-init
足以满足您的目的。没关系。有时更详细的初始化程序使得使用该类更方便。经验(和力量)将成为你的指导。
请注意,我没有在任何初始化方法中使用生成的属性访问器。如果您不是环境要求,通常应该避免在-init方法和-dealloc中使用属性访问器,这主要是因为自动键值编码通知的副作用可能会产生痛苦的问题。
初始化器和dealloc方法在类中起着特殊的作用。作为类设计者,您有责任在这些方法中设置和清理实例变量。一个好的经验法则是为您的类的调用者保留合成属性访问器的使用,以及在类中实现其他方法。
在进行实例初始化或解除分配时,您可以而且应该直接触摸ivars。他们是你的。你声明了它们,所以你可以直接处理它们。在您的类中实现其他方法时,通常应该使用属性访问器。
JeremyP关于对象的Cocoa概念文档的链接是一个很好的链接。您一定要阅读有关对象的部分,并在您获得编写自己的自定义类的更多经验时定期重新阅读它。最终,它将开始有意义。