Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

pwhisler

macrumors newbie
Original poster
Sep 23, 2008
5
0
I am trying to change the animation of objects based on their present state. I had this working fine, but then I used the instruments tool and noticed that I had all kinds of memory leaks. I have tried to fix this by two ways, but they cause a crash, can anyone help me figure this out?

So here is a set up function I used to assign the animation:

Code:
- (void) setup: (NSString*) animation {
		
	// assign the image
	
	sprite = [[UIImageView alloc] initWithFrame:CGRectMake(100.0, 400.0, 75.0, 75.0)] ;
			
	animationCenter = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4" ofType:@"gif"]],
						  nil];
	
	animationLeft = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Left" ofType:@"gif"]],
					   nil];
	
	animationRight = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Right" ofType:@"gif"]],
					   nil];
	
	animationCrouch = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Crouch" ofType:@"gif"]],
					  nil];
	
		
	if(animation == @"center") {
		sprite.animationImages = animationCenter;
	}
	else if(animation == @"left") {
		sprite.animationImages = animationLeft;
	}
	else if(animation == @"right") {
		sprite.animationImages = animationRight;
	}
	else if(animation == @"crouch") {
		sprite.animationImages = animationCrouch;
	}

	[self addSubview:sprite];
	
}

and I would just call [myCharacter setup:mad:"right"]; for example to change the animation, which would work fine, but I think because every time I call setup I am reallocating "sprite" and the animations, it causes a leak.

so my next step was to change the setup function so that it just allocates that stuff, so it would look like this:
Code:
- (void) setup {
		
	// assign the image
	
	sprite = [[UIImageView alloc] initWithFrame:CGRectMake(100.0, 400.0, 75.0, 75.0)] ;
			
	animationCenter = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4" ofType:@"gif"]],
						  nil];
	
	animationLeft = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Left" ofType:@"gif"]],
					   nil];
	
	animationRight = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Right" ofType:@"gif"]],
					   nil];
	
	animationCrouch = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Crouch" ofType:@"gif"]],
					  nil];
	
		
	
	
}

and then I would have another function called update that would reassign the animations, without having to reallocate anything like this:

Code:
-(void) update:(NSString*) animation {

	if(animation == @"center") {
		sprite.animationImages = self.animationCenter;
	}
	else if(animation == @"left") {
		sprite.animationImages = self.animationLeft;
	}
	else if(animation == @"right") {
		sprite.animationImages = self.animationRight;
	}
	else if(animation == @"crouch") {
		sprite.animationImages = self.animationCrouch;
	}
	
	
	[self addSubview:sprite];  
}

but for some reason, when I try this, it causes a crash...

so the last thing I tried was to store things that changed in temp variables, assign them to the things I retain, and then release the temp variables like this:

Code:
- (void) setup: (NSString*) animation {
		
	// assign the image
	NSArray *a,*b,*c,*d;
	
	temp = [[UIImageView alloc] initWithFrame:CGRectMake(100.0, 400.0, 75.0, 75.0)] ;
			
	a = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4" ofType:@"gif"]],
						  nil];
	
	b = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Left" ofType:@"gif"]],
					   nil];
	
	c = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Right" ofType:@"gif"]],
					   nil];
	
	d = [NSArray arrayWithObjects:
					   [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ship_4_Crouch" ofType:@"gif"]],
					  nil];
	
	
	self.animationCenter = a;
	self.animationLeft = b;
	self.animationRight = c;
	self.animationCrouch = d;
		
	if(animation == @"center") {
		temp.animationImages = animationCenter;
	}
	else if(animation == @"left") {
		temp.animationImages = animationLeft;
	}
	else if(animation == @"right") {
		temp.animationImages = animationRight;
	}
	else if(animation == @"crouch") {
		temp.animationImages = animationCrouch;
	}
	
	xPos = 50.0;
	yPos = 230.0;
	
	self.sprite = temp;
	[temp release];
	[a release];
	[b release];
	[c release];
	[d release];
	
	

	[self addSubview:sprite];

	
}

if I have the [a b c d release] thing above, that causes a crash, if I don't release them, I still have the memory leak. Anyone know how I can fix this, what I am doing wrong? Or should I not really worry about the memory leak?
 

tpaustin

macrumors newbie
Oct 7, 2008
1
0
Do you need to add the subview every time

I'm new to this Objective-C\Mac stuff, but it seems like you only need to change the images and not add the subview every time you update the images?
 

detz

macrumors 65816
Jun 29, 2007
1,051
0
Make two functions, one setup and one changePosition. Keep the init stuff in setup and move the condition(if center....etc) to the change Position function. Then, just call the changePosition function. Once you've loaded the images you don't need to keep recalling them, you're wasting resources and cpu time to reload them just to change positions.
 

pwhisler

macrumors newbie
Original poster
Sep 23, 2008
5
0
yea, so to solve it, i just changed the position, so the animation that is not being used is off screen, then when i need to change it i just swap positions...

thx
 

Sendel

macrumors newbie
Feb 5, 2009
5
0
may be...

when I understand the (ugly) way of handling objects in objective c right, then you can not release objects you never allocated by your self. BUT if you do so, don't forget to set it to nil, when you will use it somewhere else, too.
PHP:
[NSArray arrayWithObjects:{objects}]
NSArray is allocating for you, so it would be better not release it, NSArray will do. But if you still want to do it, you should ground it to nil, so your Application will not crash when you are still trying to use it:

PHP:
self.myArray = [NSArray arrayWithObjects:{objects}];
[self.myArray release];
if (self.myArray) {
    // will always give "true", because pointer still exists.
}
self.myArray = nil; // ground pointer to zero.

// now your application will not crash even with still accessing it:
[myArray addObject:{object}] // your application will skip this call without error

Imho you cannot compare string like this :
PHP:
if ( stringA == @"test" ) { /* do some mind-blowing stuff*/ }
instead you should use :
PHP:
if([stringA compare:@"test"] == NSOrderedSame) { /* do some mind-blowing stuff*/ }

good luck,
Sendel
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.