0

ARC が ARC を蹴っている

cocos 2d をインストールしましたが、ARC を使用したかったので不満でした。よくわからないという問題が発生しています。

Instruments は、GraphicsManager オブジェクトへの参照が 5 つあると言っていますが、そのうちの 4 つしか結論付けることができません。これらの多くを作成してリリースする必要があります。

クラス "RowManager" (CCLayer) は、クラス "GraphicsManager" (CCNode) を呼び出して、これらのオブジェクトを作成します。RowManager はそのメソッドを呼び出して、セレクターを介してオブジェクトを移動します: [self schedule:@selector(row:) interval:.01]

最後に、オブジェクトがポイントに到着すると、メソッド「row1Finished」が呼び出され、オブジェクトへの参照をもう 1 つ作成してから、オブジェクトを呼び出して (死ぬ) 自身の子を削除します。

3 つのアニメーションすべてを停止し、オブジェクトを RowManager から切り離して非表示にすることができますが、dealloc メソッドはまだそれ自体を呼び出しません。私は何を間違っていますか?

arc 以外の cocos2d テンプレートを変換するには、次の手順に従いました。

http://www.learn-cocos2d.com/2012/04/enabling-arc-cocos2d-project-howto-stepbystep-tutorialguide/

/////////////////

@interface RowManager : CCLayer {
    GraphicsManager *graphicsObject;
}

@implementation RowManager
-(id) init
{
    if( (self=[super init]) ) {

        graphicsObject = [[GraphicsManager alloc] initWithBoatType:@"flatboat" withWord:@"life" usingCharacter:@"Puchai" orientation:@"up" visible:YES];
        graphicsObject.tag = 21;
        graphicsObject.position = ccp(offset,size.height/4.1);
        [self addChild: graphicsObject];
        [self schedule:@selector(row1:) interval:.01];
        [self schedule:@selector(rotate:) interval:6];

// etc…


-(void)row1:(ccTime)dt{
    // scroll the object across the screen
    graphicsObject = (GraphicsManager *)[self getChildByTag:21]; // reference: for the row method
    graphicsObject.position = ccp(graphicsObject.position.x-1, graphicsObject.position.y);
    if (graphicsObject.position.x < 0 - graphicsObject.boatWidth){
        [self row1Finished];

    }
}

-(void)rotate:(ccTime)dt {
    //waggle the object a bit
   graphicsObject = (GraphicsManager *)[self getChildByTag:21]; // reference 2: for the rotate method
    [graphicsObject runAction:[CCSequence actions:
                               [CCRotateBy actionWithDuration:1 angle:.8],
                               [CCRotateBy actionWithDuration:2 angle:-.8],
                               [CCRotateBy actionWithDuration:1 angle:-.8],
                               [CCRotateBy actionWithDuration:2 angle:.8],
                               nil]];
}
-(void) row1Finished {

    graphicsObject = (GraphicsManager *)[self getChildByTag:21]; // reference 3: to reference the referenced

    [self unschedule:@selector (row1:)];
    [self unschedule:@selector(rotateBoat:)];
    [graphicsObject die];  // call within object class to remove references
    [self removeChild:graphicsObject cleanup:YES];
    graphicsObject = nil;
}

/////////////////////

in Graphics Manager Class:

///////////////////


@interface GraphicsManager : CCNode {...}
@property CGFloat boatWidth;
…etc

@implementation GraphicsManager
@synthesize boatWidth;
- (void) die {

    [self unschedule:@selector(puchaiRow:)]; // reference 4 animation 
    [self stopAllActions];
    [self removeAllChildrenWithCleanup:YES]; // removes sub objects created in class

    NSLog(@"Died");
}
- (void)dealloc
{
    CCLOG(@"Graphics Manager dealloc: %@", self);
}

-(id)initWithBoatType:(NSString *)boatType orientation:(NSString *)orientation
{

    self = [super init];
    if (self){

        if ([orientation isEqual: @"upstream"]){

            flatBoat = [CCSprite spriteWithFile:@"flatBoat.png"];
            flatBoat.anchorPoint = ccp(0,0);
            self.boatWidth = [flatBoat boundingBox].size.width;
            [self addChild:flatBoat];

            [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"puchai.plist"];
            puchai = [CCSprite spriteWithSpriteFrameName:@"puchai1.png"];
            puchai.anchorPoint = ccp(0,0);
            puchai.position = ccp(20,30);
            puchai.tag = 4;
            [self addChild:puchai];

            [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"cube.plist"];


            cube = [CCSprite spriteWithSpriteFrameName:@"cube1.png"];
            cube.scale = .80;
            cube.tag = 56;
            cube.visible = NO;
            cube.position = ccp(150,45);
            [self addChild:cube];

            cube = [CCSprite spriteWithSpriteFrameName:@"cube2.png"];
            cube.scale = .80;
            cube.position = ccp(-1 +150,[cube boundingBox].size.height +45);
            cube.tag = 57;
            cube.visible = NO;
            [self addChild:cube];


           [self schedule:@selector(puchaiRow:) interval:3]; // reference 4 animation

            flatBoatWing = [CCSprite spriteWithFile:@"flatBoatWing.png"];
            flatBoatWing.anchorPoint = ccp(0,0);
            flatBoatWing.position = ccp(25,17);
            [self addChild:flatBoatWing];


        }
///etc

-(void)puchaiRow:(ccTime)dt{

    puchai = (CCSprite *)[self getChildByTag:4];
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"puchai.plist"];
    NSMutableArray *frames = [[NSMutableArray alloc]init];
    for (int i = 1; i<=8; i++) {

        NSString *frameName = [NSString stringWithFormat:@"puchai%i.png",i ];
        [frames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache]
                           spriteFrameByName:frameName]];
    }
    CCAnimation *a = [CCAnimation animationWithSpriteFrames:frames delay:1.0f/5.0f];
    [puchai runAction:[CCAnimate actionWithAnimation:a]];

////////// これがzombies:historyの出力です。

#   Address Category    Event Type  RefCt   Timestamp   Size    Responsible Caller
0   0x13ea95e0  GraphicsManager Malloc  1   00:02.748.439   208 -[RowManager init]
1   0x13ea95e0  GraphicsManager Retain  2   00:02.748.447   0   -[GraphicsManager initWithBoatType:withWord:usingCharacter:orientation:visible:]
2   0x13ea95e0  GraphicsManager Release 1   00:02.748.449   0   -[GraphicsManager initWithBoatType:withWord:usingCharacter:orientation:visible:]
3   0x13ea95e0  GraphicsManager Retain  2   00:02.841.543   0   -[CCScheduler scheduleSelector:forTarget:interval:paused:repeat:delay:]
4   0x13ea95e0  GraphicsManager Retain  3   00:02.841.572   0   ccArrayAppendObjectWithResize
5   0x13ea95e0  GraphicsManager Retain  4   00:03.477.669   0   -[RowManager row1:]  <--- AHA!!!! 
6   0x13ea95e0  GraphicsManager Retain  5   00:03.482.438   0   -[RowManager row1Finished]
7   0x13ea95e0  GraphicsManager Release 4   00:03.482.439   0   -[RowManager row1Finished]
8   0x13ea95e0  GraphicsManager Release 3   00:03.482.480   0   -[CCScheduler removeHashElement:]
9   0x13ea95e0  GraphicsManager Release 2   00:03.483.435   0   ccArrayRemoveObjectAtIndex
10  0x13ea95e0  GraphicsManager Release 1   00:03.483.436   0   -[RowManager row1Finished]
4

3 に答える 3

0

すべきです[self unschedule:@selector (row1:)];[self unschedule:@selector (row:)];?これにより、余分な参照が生き続けます。

于 2013-04-09T12:00:42.620 に答える
0

ゾンビの歴史をもう一度見直して問題を解決しました。row1 では、row1finished を呼び出した後にオブジェクトを nil に設定しなかったため、法律に違反しています。同じクラスの参照ごとに、すべての参照をゼロに「無効化」する必要があります...

話の教訓: バグを見つけるのが困難だった理由は、row1 ルーチンをスケジュールして約 50 回実行させたため、ゾンビの履歴に多数の保持リリースが発生し、削除によって削減できなくなったためです。周囲のコードをコメントアウトしてすべてを取り除き、解析できるゾンビの出力を取得することができました。

ご意見をお寄せいただきありがとうございます。楽器の使い方が少し上手になった気がします!

-(void)row1:(ccTime)dt{

    graphicsObjectRow1 = (GraphicsManager *)[self getChildByTag:11];
    graphicsObjectRow1.position = ccp(graphicsObjectRow1.position.x + 1,graphicsObjectRow1.position.y);

   // if (graphicsObjectRow1.position.x > screenX/4){
        [self row1Finished];
    graphicsObjectRow1 = nil;
        // graphicsObjectRow1.position = ccp(offset,size.height/4.1);
   // }

}
于 2013-04-09T14:58:11.003 に答える
0

(__bridge id)ARCから除外するために使用できます。除外して手動のRetain-Releaseを使用する必要があるものは何ですか。

于 2013-04-09T09:03:14.570 に答える