ImageIO initImageJPEG instances getting allocated and never released
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 开发者_StackOverflow*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];
Any help to find what the error is?
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.
Does anyone have an answer for this? It's tearing me apart trying to figure out why this image information keeps lingering. I've tried every solution.
The situation:
Images get downloaded and stored to the device, then loaded with imageWithContentsOfFile (or even initWithContentsOfFile, which doesn't help either). When the view goes away, the images don't, but they don't show up as leaks, they're just this initImageJPEG Malloc 9.00 KB that never goes away and keeps ramping up.
UPDATE: I believe I've figured this out: Check to make sure everything is actually getting dealloc'd when you're releasing whatever the parents (and/or grandparents) and etc of the images are. If the parents don't get deallocated, they never let go of their children images, and whatever data was in those images sticks around. So check retain counts of parent objects and make sure that everything's going away all the way up whenever you release the view at the top.
A good way to check for this is to put NSLogs into custom classes' dealloc methods. If they never show up, that object isn't going away, even though the reference to it might, and it (and whatever its subviews and properties are) will never ever disappear. In the case of images, this means a pretty sizable allocation every time that object is generated and never deallocated. It might not show up in leaks, especially if the parent of the topmost object you're thinking you're releasing but actually aren't persists and doesn't itself ever deallocate.
I hope this helps. It'll be useful to take some time to read through your code with a fine-toothed comb to make sure you're allocating and releasing things properly. (Search for "alloc]", start at the top of the file, and work your way down to make sure you're releasing and that the release isn't inside of some if() or something.)
Also, running "Build and Analyze" might lock up your machine for a bit, but its results can be really helpful.
Good luck!
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.
精彩评论