views:

102

answers:

3

I got this error from XCode:

objc[8422]: FREED(id): message release sent to freed object=0x3b120c0

I googled and find that is related to the memory. But I don't know which line of code I go wrong, any ideas? After I launch my app in simulator, it prompts a second, than, no other error except the error above.

@implementation MyAppDelegate

@synthesize window;
@synthesize viewController;


- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after app launch    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    [self changeScene:[MainGameMenuScene class]];
}


- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

- (void) changeScene: (Class) scene
{
    BOOL animateTransition = true;

    if(animateTransition){
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.5];
        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:window cache:YES]; //does nothing without this line.
    }

    if( viewController.view != nil ) {
        [viewController.view removeFromSuperview]; //remove view from window's subviews.
        [viewController.view release]; //release gamestate 
    }

    viewController.view = [[scene alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT) andManager:self];

        //now set our view as visible
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    if(animateTransition){
        [UIView commitAnimations];  
    }   
}
+3  A: 
[viewController.view release]; //release gamestate

That's an extra release (if you didn't alloc it, don't release it). A couple lines down:

viewController.view = [[scene alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT) andManager:self]; 

will release viewController.view again before retaining the new value, that will over-release the view and cause a crash (it sends the release message to an object that has already been dealloc'd / memory that has already been freed). Instead, try:

scene *view = [[scene alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT) andManager:self];
viewController.view = view; // setView will release the old/retain the new
[view release];             // so you don't need to worry about releasing it later
dbarker
can I instead retain the controller.view before removeFromSuperview?
Tattat
shouldn't need to retain or release it - especially if you're about to replace it with a newly alloc'd view.
dbarker
A: 

Got the solution:

- (void) changeScene: (Class) scene
{
    BOOL animateTransition = true;

    if(animateTransition){
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.5];
        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:window cache:YES]; //does nothing without this line.
    }

    if( viewController.view != nil ) {
        [viewController.view retain]; //retain the view.
        [viewController.view removeFromSuperview]; //remove view from window's subviews.
        [viewController.view release]; //release gamestate 
    }

    viewController.view = [[scene alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT) andManager:self];

        //now set our view as visible
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    if(animateTransition){
        [UIView commitAnimations];  
    }   
}

It needs me to retain the view, but I don't know why this is necessary.

Tattat
This is totally unnecessary. You shouldn't be releasing the view in the first place because it is a property of another object.
TechZen
But I may reuse this method to do change scene, should I keep this way?
Tattat
A: 

This line:

[viewController.view release];

Is most likely your problem. Never send release to a property of an object except in the class' dealloc method. The view controllers view property accessors will handle retaining and releasing for you.

TechZen