Just spent countless hours over the past 10 days fighting a single bug in my next app. If you restarted the game, the app crashes. Took forever to figure out why. Turns out I was releasing memory that I shouldn’t have. That’s what I get for being a tidy programmer! UGH!
See highlighted block at the end of the snippet below.
-(id) initWithParentNode:(CCNode*)parentNode Player:(NSInteger)player Icon:(NSInteger)icon Color:(NSInteger)color{ // always call "super" init // Apple recommends to re-assign "self" with the "super" return value if( (self=[super init])) { CGSize winSize = [[CCDirector sharedDirector] winSizeInPixels]; NSString *strFile = [[NSString alloc] init]; if ((color == -1) && (icon == -1)) strFile = @"player_silver_car.png"; else { switch (color) { case 0: strFile = @"player_blue_"; break; case 1: strFile = @"player_yellow_"; break; case 2: strFile = @"player_red_"; break; case 3: strFile = @"player_green_"; break; } switch (icon) { case kPlayerChicken: strFile = [strFile stringByAppendingString:@"chicken.png"]; break; case kPlayerBoard: strFile = [strFile stringByAppendingString:@"board.png"]; break; case kPlayerTruck: strFile = [strFile stringByAppendingString:@"truck.png"]; break; case kPlayerCar: strFile = [strFile stringByAppendingString:@"car.png"]; break; } } playerLap = 1; playerSwipes = 0; playerSprite = [CCSprite spriteWithFile:strFile]; // Get Audio File audioSoundFile = [self getAudioFile:icon]; // Load the Lap Sprites // CCFadeOut *fo = [CCFadeOut actionWithDuration:.1]; lapSprite1 = [CCSprite spriteWithFile:@"lapindicator1.png"]; lapSprite1.position = CGPointMake(winSize.width/2, winSize.height/2); lapSprite1.opacity = 0; lapSprite2 = [CCSprite spriteWithFile:@"lapindicator2.png"]; lapSprite2.position = CGPointMake(winSize.width/2, winSize.height/2); lapSprite2.opacity = 0; lapSprite3 = [CCSprite spriteWithFile:@"lapindicator3.png"]; lapSprite3.position = CGPointMake(winSize.width/2, winSize.height/2); lapSprite3.opacity = 0; [parentNode addChild:lapSprite1]; [parentNode addChild:lapSprite2]; [parentNode addChild:lapSprite3]; // [lapSprite1 runAction:fo]; // [lapSprite2 runAction:fo]; // [lapSprite3 runAction:fo]; // // Get start position from the bundle RaceLayer *rl = (RaceLayer*)parentNode; if (player == 1) startPoint = rl.currentTrack.startPosition1; else startPoint = rl.currentTrack.startPosition2; rl = nil; [playerSprite setPosition:startPoint]; [parentNode addChild:playerSprite z:10 tag:kTagSpritePlayer + playerNumber]; playerSprite.rotation = -90; playerStuckCount = 0; soundOn = true; /* * Keeping this here for posterity. * This one line actually creates a bug that prevents the screens from being reloaded * It took me part-time work over 10 days to find this one error. * I had to completely rip the code apart and slowly add parts back until I found the bug. * COCOS2D caches images so it only loads them once. * My assumption for the error is that by releasing the filename, when COCOS2D checks to see if the image is cached, * the memory has been released and it throws a "BAD_ACCESS" error but does NOT say why. * [strFile release]; */ // Manually schedule update via the undocumented CCScheduler class. [[CCScheduler sharedScheduler] scheduleUpdateForTarget:self priority:0 paused:NO]; } return self; }