1

我有这样的代码:

我的类.h

@interface MyClass : CCLayer {

}

@property (nonatomic, retain) CCSprite *spriteName;  //retain count = 1
@property (nonatomic, retain) CustomClass *customVariable; //retain count = 1

@end

我的班级.m

@implementation MyClass
@synthesize spriteName;
@synthesize customVariable;

//rough init method
-(void)init 
{
    self.spriteName = [CCSprite spriteWithFileName:@"a.png"]; //retain count = same
    self.customVariable = [[CustomClass alloc] init]; //retain count = 2
}

-(void)dealloc
{
    [self.spriteName release]; //retain count = 0
    self.spriteName = nil;

    [self.customVariable release]; //retain count = 1?
    self.customVariable = nil;

    [super dealloc];
}

我对此有一些疑问:

1) 我有一个 CCSprite,我已经将它做成了一个属性,但是当我将它分配给 时[CCSprite spriteWithFileName:@"a.png"],它是一个自动释放的对象。但是因为我有@property (nonatomic, retain) CCSprite *spriteName,我必须释放它是吗?

2)对于我的customVariable,以上述方式释放它时似乎出现错误,但是当我将它们更改为下划线时[_customVariable release]; _customVariable = nil,我没有收到错误。为什么会这样,两者有什么区别?

3)我释放这些对象对吗?我在保留计数中发表了评论,我认为我无法理解。如果有分配或保留,我知道基本知识,那么我应该 +1,但在属性方面我很困惑。

4

1 回答 1

3

因此,对这些 iVar 的完整处理如下。编译器会像这样默默地处理您的代码:

@interface MyClass : CCLayer {
    CCSprite *_spriteName;
}

@property (nonatomic,readwrite, retain) CCSprite *spriteName;  //retain count = 1

@end

@implementation MyClass
@synthesize spriteName=_spriteName;

@end

在您的代码中,“readwrite”和 iVar 的名称是隐式的 (_spriteName),编译器会生成相应的代码。但是,您可以使用不同名称的 iVar 来指向实际的 CCSprite。使用 self.spriteName 语义,编译器在后台转换(自动生成)代码。在您的示例中,编译器为“self.spriteName”(合成)生成了一个 setter 和一个 getter,如下所示:

-(void) setSpriteName:(CCSprite*) theSpriteName {
   // this setter can be quite tricky depending on the @property clause 
   // but for this example, a simplified setter :

    [_spriteName autorelease];  
    _spriteName = [theSpriteName retain]; 

}
-(CCSprite*) spriteName {
    return _spriteName;
}

因此,当您使用 self.spriteName 时,根据上下文(lhs 或 rhs),会调用适当的“隐藏”例程。所以这条线

self.spriteName = [CCSprite spriteWithFileName:@"a.png"];

实际上调用上面生成的设置器(setSpriteName)。反过来

CCSprite *tempSprite = self.spriteName;

调用生成的 getter。您始终可以自由使用“基础”iVar。

CCSprite *otherTempSprite = _spriteName; // exactly the same.

但是,在更改 _spriteName 的内容或更改其生命周期时要非常谨慎,因为您可能会意外地造成泄漏或僵尸,直到您完全了解其内部结构。在 dealloc 中,使用

[_spriteName release]; // in dealloc, release immediately.

或者

self.spriteName=nil;   // will invoke the setter above, and the 
                       //   actual release could be delayed

最后,回到您的 customVariable 问题。你的代码实际上变成了

[_customVariable release];  // retain count is 0 !!! 
[self setCustomVariable:nil]; 

which when called will execute :

[_customVariable autorelease]; // bad access : message sent to a deallocated variable 
_customVariable=nil;
于 2012-11-12T10:16:19.533 回答