releasing views in iPhone [duplicate] - iphone

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
calling [myString release] does NOT decrement [myString retainCount]
I am in very big problem please help me to solve the same.
I am creating a view in custom way as
UIView *view = [self getCustomVIew:index];
[view release];
view = nil;
In getCustomVIew:index, I am allocating and returning the view. When I release view as
[view release];
it is not releasing the view from getCustomView:index and the reference count is not decremented.
Please help me to release the view returned from getCustomVIew:index and to maintain the memory size.
Instruments is just increasing the overall size of program when the views get deleted.

You don't need to release view from that getCustomVIew method. Returned view from should be already marked as autorelease
-(UIView*) customView{
UIView *v = [[UIView alloc] init];
...
return [v autorelease];
}

You need not to release that view in getCustomVIew:. Instead send autorelease signal before returning. After you get that view object also, you need not to release since it is already autoreleased.

your code seems fine and if you are trying to use "view.reatinCount" to ensure that view is released, it is not good.
here is the exact duplicate issue you may refer:
calling [myString release] does NOT decrement [myString retainCount]

Related

Object dealloc only crashes in iOS 4.3

I'm trying to figure out why pushing a viewController in my tableView using didSelectRowAtIndexPath would cause a crash in iOS 4.3, but in iOS 5.0+, it works fine.
It crashes right when I call:
self.customViewController = [[[CustomViewController alloc] initWithNibName:#"CustomViewController"bundle:nil] autorelease];
anytime after the first time the customViewController has been pushed.
Here's my relevant code:
#property (nonatomic, retain) CustomViewController *customViewController;
-(void) dealloc // Dealloc of tableView.
{
[customViewController release];
customViewController = nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.customViewController = [[[CustomViewController alloc] initWithNibName:#"CustomViewController"bundle:nil] autorelease]; // Release old, allocate new, set it.
[[self navigationController] pushViewController:customViewController animated:YES];
[customViewController release]; // Balance out pushViewController's retain.
}
Thanks.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.customViewController = [[[CustomViewController alloc] initWithNibName:#"CustomViewController"bundle:nil] autorelease];
[[self navigationController] pushViewController:customViewController animated:YES];
[customViewController release]; // Balance out pushViewController's retain. ---->NO
}
The last release is an extra one that is not needed.
You already have done an autorelease on it to have it's retain count down by one.
We will analyse this line
self.customViewController = [[[CustomViewController alloc] initWithNibName:#"CustomViewController"bundle:nil] autorelease];
you create a CustomViewController retain count == 1.
You say autorelease on it so retain count will be 0 later (probably the end of the run loop), but for now it's still 1 that is why you still have access to it, but treat it as 0.
After that you say self.customViewController, that property is retain, so retain count == 1.
And you are taking care of that 1 in your dealloc.
As of your comment :
// Balance out pushViewController's retain.
You don't Balance those, you balance only the one YOU own. If the system make retain on your objects, it will release them when the system don't need them anymore.
Don't release the customViewController. You've already autoreleased it when you assigned it, so you've already given up ownership from the alloc. You don't have to release or autorelease the object again. The navigation controller takes ownership and will relinquish it by itself at the appropriate time.
Also, it's coincidence that you may see it in one version and not another. This is a memory management problem, so any corruption you might see (crashes, etc.) will be dependent on the state of memory on the device whenever you run the app. You may see a crash all the time, never, or only after running Skype but before opening the Photos app.
A good way to look for these is to enable zombies during your debugging sessions. With zombies enabled, objects are never actually released. Instead they are put into a zombie state and if they're ever sent a message again, they will abort the app and show you where the stray message was sent to help you debug your memory issues.

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 has 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 IBOutlets (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];

How does a UILabel/UIbutton etc works even after releasing them from memory?

For example:
UILabel *lblEmail = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 70, 30)];
[lblEmail setBackgroundColor:[UIColor clearColor]];
[lblEmail setText:#"Email"];
[lblEmail setTag:1];
[contentView addSubview:lblEmail];
[lblEmail release];
In the above code, we create one UILabel and release it and hence has no memory reference anymore, but still it's works while I am running the application. and we can change it's value using viewWithTag also. Other example would be I create one button and release it but still in the when user clicks on the buttons it works.
Content view retained the label / button, so it is still around. You create it with a retain count of 1, adding it to the contentView gives it a retain count of 2, and releasing it gives it a retain count of 1. So it is still around.
It's not released from memory. You are just releasing your retention of it. When you add it as a subview of contentView it is retained internally there.
Apple Docs states - (void)addSubview:(UIView *)view retains view and sets the view’s next responder to the receiver, which is its new superview.
lblEmail will only be deallocated once it's reference count is 0. It is retained by contentView.
Read the Apple Documentation for addSubview.
- (void)addSubview:(UIView *)view
The view to be added. This view is retained by the receiver
Apple Documentation for UIView

UIWebView memory issues

I am playing youtube videos on a UIWebView which appears as a modalViewController subview (flip transition). Everything works fine, even though the UIWebView is released, I still receive memory warnings after a few repeated selection of this modalViewController.
I have added my UIWebView programmatically inside ViewDidLoad. Inside viewDidDisappear I check for [UIWebView retainCount] and if greater than 1, perform the following steps:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[self.webView removeFromSuperview];
self.webView.delegate = nil;
self.webView = nil;
NSLog(#"[self.webView retainCount] %d", [self.webView retainCount]);
I am running my code on xCode 3.2.5, iOS 4.2.
Appreciate all you help.
I think you are approaching the memory management problem in the wrong way. Checking the retainCount is a valid debugging technique if you know what you are doing. It is not, however, a memory management tool. In your particular case, if the UIWebView is being displayed it will always have retain count > 1. The superview will have a retain on it thus making the "if" useless.
If the webView property is well defined (i.e. noatomic, retain) the statement:
self.webView = nil;
should release the webView. A common mistake is to initialize the property with:
self.webView = [[UIWebView alloc] init];
This is likely to introduce a leak if the webView is defined as "retain". The correct way is
self.webView = [[[UIWebView alloc] init] autorelease];
If you can't display your controller several times without running out of memory you have a memory leak. Use Instruments (Leaks in particular) to find hte objects what are note being released properly. This is a good tutorial.
Be careful in keeping your retains and releases balanced and check for leaks.
Your problem will be related to this:
Is it possible to prevent an NSURLRequest from caching data or remove cached data following a request?
Scroll down to my answer for an extension of the accepted answer - i had this problem for days and it's now resolved!

How to right dealloc object when app goes to background?

Have only one question "How to right dealloc object when app goes to background ?". I'm working on some app, everything works great and fine. When i put app to background and then start it again it's crashes. Not immediately(app stars right where i closed it) , but when i choose some of cells or just scroll tableview for example. So i'm pretty sure that app calls already released data.
here is example of dealloc
- (void)dealloc {
[anObject release];
[array release];
[locationManager release];
[currentLatitude release];
[currentLongitude release];
[filteredListContent release];
[super dealloc];
}
Any advises?
Unless you specifically deallocate things in your app delegate's applicationDidEnterBackground method, nothing should be deallocated for you automatically.
I have never experienced the problem you're having. Are you certain the same thing doesn't happen after a while even if you never put it in the background?
Here's a good explanation of how all of the backgrounding stuff fits together:
Understanding iOS 4 Backgrounding and Delegate Messaging
I review and re-write my own code. The problem was as i expected in deallocation of memory. I used autorelease where i shouldn't. It still weird cause app did crash when i open it again.
Thanks everyone, not you guys who gift to me 2 negs, you are jerks. Don't be offended,but instead of give some advise you just give ungrounded negs.
Never release any object like this. Use
- (void)dealloc {
if(anObject){
[anObject release];
anObject = nil;
}
if(array){
[array release];
array = nil;
}
//same approach for all.
[super dealloc];
}