UIImageView got weird retain count and i need to release it twice to avoid leaks
I got a UIImageView that i set in the nib file. I download an image from internet and sets the image to the UIImageView. When i'm releasing it h开发者_JAVA百科as retain count 2? If i'm using only 1 release it won't show any memory leak but i can see in "Instrument Allocations" that it never gets released. When i release the UIImageView twice like below then it works good. But i should never release it twice?!?!
in Header:
IBOutlet UIImageView *background;
in the .m loading the image:
/* Load Image code */
id path = [NSString stringWithFormat:@"http://www.image.com/aImage.jpg"];
NSURL *url = [NSURL URLWithString:path];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData* urlData = [[NSData alloc] initWithContentsOfURL:url];
[background setImage:[UIImage imageWithData:urlData]];
[urlData release];
[pool release];
in dealloc function:
- (void)dealloc {
NSLog(@"Backgroud count: %i",[background retainCount]); // Prints 2
[background release];
[background release]; // Does not "leak" if i have 2x release
[super dealloc];
}
This is the only code that is useing the UIImageView Background.
EDIT:
something i forgot to mention is that i run this code inside a for loop like this. but this for loop will only execute once! But it shouldn't matter?
for (id theKey in dictionary) {
/* Load Image code above is here */
}
I believe that I've figured out what the trouble is. Apple recommends that you retain the objects you connect to through IBOutlet
s (your image view, in this case). You said that you haven't done so, but you should be following Apple's recommendation. The reason that you should is outlined in a iphonedevsdk.com forum post about this problem, which links to a Big Nerd Ranch blog post that lays it all out.
On iOS, the nib loading mechanism uses the setter if your outlet has one, but it uses key-value coding if not; specifically, it uses setValue:forKey:
, which retains the value (this is documented, but somewhat unexpected). Your image view, being the subview of your view controller's top view, is retained by that view. It's also retained by this key-value setting procedure. So, unbeknownst to you, your objects have two references to the image view. Apple makes the retaining property suggestion so that it becomes knownst to you that the view is being retained.
You still shouldn't be worrying about the retain count as such, but you should do one of two things: make this IBOutlet
a retained property and release it in both viewDidUnload
and dealloc
(just once each, though!), or follow BNR's suggestion and make the property explicitly assigned:
@property (assign, nonatomic) IBOutlet UIImageView *background;
in which case you do not have to release it yourself. In both cases, make sure you @synthesize
the property accessors.
Previously:
Don't look at retain count, and if there's no leak being detected, then don't worry about it. The UIKit framework is likely retaining the view for reasons that you aren't privy to.
Additionally, if background
isn't a retained property:
@property (retain) IBOutlet UIImageView *background;
and you're creating it in the xib, you shouldn't be releasing it at all, because you don't own it. That is, you aren't responsible for its memory; the actions that give you that responsibility are: calling retain
on the object, or creating it using a method whose name begins with alloc
, copy
, mutableCopy
, or new
.
I don't know much about nib file, i used to follow like below
background=[[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)]; //Now the reatin count is 1 [background setImage:[UIImage imageWithData:urlData]]; [someView addSubview:background]; //Now the ratainCount will be 2 since we added the imageview to the superview [background release]; //i will release immediately so the retain count drops to 1 . . . //in dealloc or viewDidDisaaper i will remove the imageview from its superview //then the retainCount will become 0 and the instance will be deallocated. //it works for we without any memory leakage [background removeFromSuperview];
精彩评论