@property保留 - iPhone

时间:2011-01-14 14:30:00

标签: iphone objective-c properties retain

我是iPhone编程的新手。我有以下疑问阻止我继续前进。请考虑以下代码:

---------.h------
@interface myClass: UIViewController
{
    UIImage *temp;
}

@property (nonatomic, retain) UIImage *temp;

 ---------.m------
 @interface myClass
 @synthesize temp;

 -(void) dealloc
 {
   [temp release];
   [super dealloc];
 } 
  1. 以上是唯一的程序代码。多数民众赞成......没有别的。我是否需要在dealloc方法中声明[temp release],即使我根本没有在我的程序中使用属性访问器方法。如果我没有在dealloc中声明[temp release]怎么办?这会造成内存泄漏,因为我发布了一些我没有保留的东西,因为我没有调用属性访问器方法。

  2. 此外,当我为temp打印保留计数时,为什么它显示为0,即使它保留在@property中。

  3. 提前致谢

3 个答案:

答案 0 :(得分:1)

  1. 如果没有为myClass.temp(的一个实例)分配任何值,那么就不会有泄漏。但是你应该在你的dealloc中发布它。

  2. @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];
    
  3. 在旁注中,您应该为您的类命名以大写字母开头 信,即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概念文档的链接是一个很好的链接。您一定要阅读有关对象的部分,并在您获得编写自己的自定义类的更多经验时定期重新阅读它。最终,它将开始有意义。