views:

383

answers:

2

Hi!!

Im developing an app for an iPhone and I found that the following code is causing the memory allocation to increment.

    -(UIImage *)createRecipeCardImage:(Process *)objectTBD atIndex:(int)indx
{

[objectTBD retain];

// bringing the image for the background 
UIImage *rCard = [UIImage imageNamed:@"card_bg.png"];
CGRect frame = CGRectMake(00.0f, 80.0f, 330.0f, 330.0f); 

// creating he UIImage view to contain the recipe's data
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = rCard;

[rCard release];
imageView.userInteractionEnabled = YES;


float titleLabelWidth = 150.0;
float leftGutter = 5.0;
float titleYPos = 25.0;
float space = 3.0;
float leftYPos = 0;

// locating Title label
float currentHeight = [self calculateHeightOfTextFromWidth:objectTBD.Title :titleFont :titleLabelWidth :UILineBreakModeWordWrap];
UILabel *cardTitle = [[UILabel alloc]initWithFrame:CGRectMake(leftGutter, titleYPos, titleLabelWidth, currentHeight)];
cardTitle.lineBreakMode = UILineBreakModeWordWrap;
cardTitle.numberOfLines = 0;
cardTitle.font = titleFont;
cardTitle.text = objectTBD.Title;
cardTitle.backgroundColor = [UIColor clearColor];
[imageView addSubview:cardTitle];

[cardTitle release];

leftYPos = titleYPos + currentHeight + space;

// locating brown line
UIView *brownLine = [[UIView alloc] initWithFrame:CGRectMake(5.0, leftYPos, 150.0, 2.0)];
brownLine.backgroundColor = [UIColor colorWithRed:0.647 green:0.341 blue:0.122 alpha:1.0];
[imageView addSubview:brownLine];

[brownLine release]; 

leftYPos = leftYPos + 2 + space + space + space;

// creating the imageView to place the image
UIImageView *processPhoto = [[UIImageView alloc] initWithFrame:CGRectMake(leftGutter, leftYPos, 150, 150)];


if((uniqueIndex == indx) && (uniqueImg.imageData != nil))
{

 if([uniqueImg.rcpIden isEqualToString:objectTBD.iden])
 {
  objectTBD.imageData = [NSString stringWithFormat:@"%@", uniqueImg.imageData];
  [recipesFound replaceObjectAtIndex:indx withObject:objectTBD];


  NSData * imageData = [NSData dataFromBase64String:objectTBD.imageData];
  UIImage *rcpImage = [[UIImage alloc] initWithData:imageData];
  [imageData release];
  processPhoto.image = rcpImage;
  [rcpImage release];

 }


}
else if(objectTBD.imageData != nil)
{

 NSData * imageData = [NSData dataFromBase64String:objectTBD.imageData];
 UIImage *rcpImage = [[UIImage alloc] initWithData:imageData];
 processPhoto.image = rcpImage;
 [rcpImage release];
 [decodedBigImageDataPointers addObject:imageData];

}
else
{
 UIImage * rcpImage =  [UIImage imageNamed:@"default_recipe_img.png"];
 processPhoto.image = rcpImage;
 [rcpImage release];
}

NSlog(@" Process Photo Retain Count %i", [processPhoto retainCount]); // this prints a 1
[imageView addSubview:processPhoto]; 

NSlog(@" Process Photo Retain Count %i", [processPhoto retainCount]); // this prints a 2!!!!
//[processPhoto release];  // this line causes an error :( 



// converting the UIImageView into a UIImage
UIGraphicsBeginImageContext(imageView.bounds.size);
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[objectTBD release];

for(UIView *eachSubview in imageView.subviews)
{
 [eachSubview removeFromSuperview];
 NSLog(@"each subview retainCount %i  despues", [eachSubview retainCount]);
 // here I find that the processPhoto view has a retain count of 2 (all other views have their retain count in 1)
}

return viewImage;

}

When I checked at the instruments object allocation I found that the "GeneralBlock-9216" growing up.

Breaking down the row I found that every time I call this code, one instance of:

2 0x5083800 00:18.534 ImageIO initImageJPEG

is being allocated. Checking the call stack, the following line is highlighted:

UIImage * objImage = [UIImage imageWithData:imageData];

I've been searching for a solution without success, I do not know is someone knows where the error is.

Thanks in advantage Alejandra

+1  A: 

I think you're seeing UIImage cacheing images. There used there used to be a method something like initWithData:cache that let you turn the cacheing off. Now I think the system always caches the images automatically behind the scenes even after you've deallocted the specific instances.

I don't think its an error on your part. I think it's the system keeping data around in the OpenGl subsystem. Unless it causes a major leak, I don't think it is a problem.

TechZen
Hi Techzen!!, thanks a lot for your answer, but this issue is causing me a lot of memory allocation because, this method is called from a flowCover delegate, is the one that builds the cards. I notice that not just the UIImage is being allocated each time, also all the UIlabels that I added as a subviews to the imageView. :(
alex
Might need to see more code. This code will not leak by itself. However, if you call it repeatedly it will eat a lot of memory because it initializes a new UIImageView every time it's called and the image view retains the image. If you're calling this code repeatedly, then you will get a large stack of views complete with their images and all subviews. Instead, you should initialize one or two imageviews and then swap out the images as needed.
TechZen
Thanks TechZen!! I made some changes to the code using your recommendations and also the one posted by KatokichiSoft but I got the same problem :(I updated the code with the last version. by now with the for at the end the UIlabels allocation is not happening, but the image allocation is still appearing :(.
alex
A: 

As TechZen said, the imageWithXXX: methods cache the image inside of them while you run the program (though you release the instances after using). I recommend initWithXXX: and release API sets instead of imageWithXXX:.

Well, if you embed several debug log on your source code, check how many times is it called, and check the retain count of the instances.

As far as I can explain, that is all. I hope you will solve the problem.

KatokichiSoft
Thanks a lot KatokichiSoft, I used your recommendation and I have the same problem, I posted the last version of my code, maybe something is missed. In the instruments the output is the same, the same kind of object is appearing :(.
alex