2011-10-16 111 views
1

我有一個叫做遊戲類,它看起來有點像這樣:釋放autorelease對象爲早?

@implementation GamePlay 
-(id)init{ 
    if((self = [super init])){ 
     self.isAccelerometerEnabled = YES; 

     //ship defined in header 
     ship = [Ship shipWithParentNode:self]; 
     CGSize screenSize = [[CCDirector sharedDirector] winSize]; 
     float imageHeight = [ship spriteContentSize].height; 
     [ship setSpritePosition:CGPointMake(screenSize.width*0.5, imageHeight*0.5)]; 
    } 
    return self; 
} 

-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{ 
    CGPoint pos = [ship spritePosition]; 
    pos.x = acceleration.x * 10; 
    [ship setSpritePosition:pos]; 
} 
@end 

因此,船舶類看起來是這樣的:

@implementation Ship 

+(id)shipWithParentNode:(CCNode *)parentNode{ 
    return [[[Ship alloc] initWithParentNode:parentNode] autorelease]; 
} 

-(id)initWithParentNode:(CCNode *)parentNode{ 
    if((self = [super init])){ 
     sprite = [CCSprite spriteWithFile:@"ship.png"]; 
     SpriteLoader *spriteLoader = [SpriteLoader sharedSpriteLoader]; 
     [spriteLoader addTextureAtlas:@"Spites_default.plist"]; 
     CCAnimation *spriteAnimation = [CCAnimation animationWithFrames:[spriteLoader getSpriteFramesWithName:@"ship-" andAmount:[NSNumber numberWithInt:5]] delay:0.08f]; 
     CCAnimate *anim = [CCAnimate actionWithAnimation:spriteAnimation]; 
     CCRepeatForever *repeat = [CCRepeatForever actionWithAction:anim]; 
     [sprite runAction:repeat]; 
     [parentNode addChild:sprite z:0 tag:SHIP]; 
    } 
    return self; 
} 

-(void)setSpritePosition:(CGPoint)point{ 
    sprite.position = point; 
} 

-(CGPoint)spritePosition{ 
    return sprite.position; 
} 

-(CGSize)spriteContentSize{ 
    return sprite.contentSize; 
} 
@end 

遊戲的初始化船舶罰款並繼續修改CCSprite內船舶,並在模擬一切都很好。當在設備上運行它時,我們會得到加速計輸入。在加速度計方法中,第一行因程序不再存在而使程序崩潰。如果我看在調試器與加速計方法我看到下面的第一行設置一個斷點: 自=(遊戲*)
- >船=(船舶*)0x004701e0

如果我再繼續運行該程序,我得到這個消息: 消息發送到釋放實例0x4701e0

但我不知道爲什麼它已被釋放...並大概0x004701e0 == 0x4701e0?

非常感謝, 本

回答

3

要解釋這個問題:作爲自動釋放

  • 船舶類初始化一個精靈類並將它作爲孩子parentNode(遊戲類),它保留了精靈而不是

    • 遊戲類初始化船舶類實例Ship類本身

    Ole是正確的,Ship需要在您發佈的代碼中保留。我個人在這裏看到一個設計問題。您的Ship類應該從CCNode派生,並且您應該通過addChild將Ship添加到節點層次結構中。

    如果船隻只是從NSObject的,你最終與派生是有點像一個 「破」 節點層次:

    • cocos2d的遊戲類(即CCLayer)
    • NSObject的船級
    • 的Cocos2D包含在Ship類中但添加到GamePlay類中的CCSprite實例

    問題在於Ship類的精靈由Ship類「託管」姑娘。這意味着你有責任保留非自己的CCNode類。下面使一個更簡單,更cocos2d的符合設計,因爲它依賴於cocos2d的管理整個節點層次結構:

    • cocos2d的遊戲類(即CCLayer)
    • cocos2d的船級(自CCNode派生)
    • Cocos2D包含在Ship類中的CCSprite實例,作爲子類添加到Ship類中

    這樣您可以將Ship類作爲子類添加到GamePlay類中。 Ship類將其CCSprite實例添加到self(Ship類)中。你可以(也應該)拋棄在shipWithParentNode方法中傳遞的parentObject。在Cocos2D中,將一個節點的實例傳遞給另一個節點是相當危險的,你可能會試圖保留它,這可能導致整個場景泄漏,因爲循環保留依賴關係(保留b,b保留a,放手)。

    總體而言,這會使您的節點層次結構稍微深入一些,但管理起來要容易得多。您可以假定所有對象都來自公共基類(CCNode),您可以依靠Cocos2D在正確的時間以正確的順序取消分配節點層次結構。

  • 4

    你必須retainship-[GamePlay init](後來releasedealloc,當然)。