1

私はこのようなコードを持っています:

MyClass.h

@interface MyClass : CCLayer {

}

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

@end

MyClass.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もエラーは発生しません。これはなぜですか、2つの違いは何ですか?

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)であり、コンパイラーは適切なコードを生成します。ただし、実際のCCSpriteを指すために別の名前のiVarを使用することもできます。コンパイラは、self.spriteNameセマンティクスを使用して、内部でコードを変換(自動生成)します。あなたの例では、コンパイラは次のように'self.spriteName'(合成)のセッターとゲッターを生成しました。

-(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;

生成されたゲッターを呼び出します。「基礎となる」iVarはいつでも自由に使用できます。

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

ただし、内部を完全に理解するまで、誤ってリークまたはゾンビを作成する可能性があるため、_spriteNameのコンテンツの変更やライフサイクルの変更には十分に注意してください。デアロックでは、

[_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 に答える