My App tends to crash alot... :(
I know i've been making mistakes in deallocating the views and objects.. I just wanna knw apart from deallocating the memory in the last, how can i manage memory in between the code...
Also my most of the viewcontrollers uses -(void)ViewDidLoad to create the views..so shud i use -(void)ViewDidUnload too before deallocating the memory???
If yes, then plz guide me how to use it??
Also is there any other way to solve memory issues??? :(
Keep in mind that viewDidLoad can be called multiple times, this is especially true in low memory situations where view's can be automatically unloaded to save memory.
In this case you can either check if your object is nil before allocating it, or deallocate it in a memory warning (in didReceiveMemoryWarning, if self.view.superview == nil then things will be automatically released).
You should also get to know the profiling tools at some point, or at least the leaks profiler. In Xcode go to Run -> Run With Performance Tool -> Leaks. There are some issues with this tool you might hit, but once you come to grips you'll wonder how you lived without it (For instance if your host name has special characters in it you'll need to rename it).
If u have created any object in .h file and allocated it only once then u should deallocate that object
in this method:
-(void)dealloc
{
[myObject release];
[super dealloc];
}
but if u have created any object locally (in .m) file then release it at the place where it is not required any more.
Related
I have been struggling with memory issues in my iphone app since weeks and haven’t been able to resolve the issue yet in spite of comprehensive research online.
Here is the case:
My application communicates with the Google Analytics API and is based on 3 basic views: Main view, setup view, and a tableview view that presents the data from google (with a custom cell). I have also constructed a custom class that fetches the data from google and then kills itself when done. All the data is stored in a singelton datacenter.
All views are initiated and then released as follows:
if (self.vVisitsTabelView == nil) {
visitsTabelView *initiatevisitsTabelView = [[visitsTabelView alloc] initWithNibName:#"visitsTabelView" bundle:nil];
self.vVisitsTabelView = initiatevisitsTabelView;
[initiatevisitsTabelView release];
}
[self.navigationController pushViewController:vVisitsTabelView animated:YES];
[vVisitsTabelView release];
vVisitsTabelView = nil;
The issue is that through every loading of the view memory increases, but when the view is popped it is not releasing memory although dealloc is being called and ALL instance variables are being released. This cycle happens over an over again (while re-loading the same view) and memory consumption becomes very high. After demanding use I even got to 200mb real memory and 320 virtual on instruments. Strangely a memory warning was received only once, however my app never crashed due to low memory and instruments indicates NO leaks.
After entering background the memory is slowly being released and used by other apps, however when I return to foreground memory is reclaimed back to the level before entering background (maybe form the virtual mem?). This process takes 9 seconds and in that time the app is frozen.
Any ideas how to attack this situation? I have searched everywhere and carefully followed all guidelines.
Any lead is highly appreciated...
Please excuse me if I didn’t follow guidelines, this is my first time on this wonderful place.
Thank you, can you elaborate slightly more how to do it?
Yes; you have a memory leak. Now, the Leaks instrument may or may not tell you what is leaking. It won't detect objects that are still somehow connected to the rest of the application; i.e. if a reference to the object is retained in an NSMutableDictionary somewhere that is still in use by the app, it won't be detected.
Since you know exactly which object is being leaked, it is a matter of figuring out what has retained it, but not released it. The Allocations instrument provides for exactly this capability. Specifically, you can configure the Allocations instrument to track retain counts.
This article may help http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/.
Also, there are a number of very similar question/answers on SO that address this. There is one in the last couple of weeks that I can't find that gave a great pictorial tutorial of how to do exactly what you want.
Have you checked the retain count on your views? [theView retainCount] will do this.
Either way you should strongly consider moving to ARC which is new for iOS5. You should be able to say goodbye to all your memory management woes.
I am a former java programmer, and I am having some troubles managing the memory on cocoa touch.
In fact, I think I got the retain/release trick, but still I am not sure I got it right.
For example, I am creating and adding a subview to the main window:
aViewController=[[AViewController alloc]init];//aViewController is (nonatimic,assign), so retaincount = 1 after this line?
[self.window addsubview aViewController];
[aViewController release];//retaincount=0?
And in aViewController I have an IBAction:
[self.view removeFromSuperView];
How can I be sure the object aViewController gets completely 'deleted' and memory released after I removed it from superview (think that controller as a graphic-heavy view controller)?
Also, generally, is there a way to be sure an object is deallocated? I am aware that if I ask ownership of an object I have to release it at a certain point, but what if I just want the object's pointer to be null at a certain point(not basing on the retaincount)? Should I call dealloc directly? I find sometimes very confusing to keep under control the retain/release mechanism.
If someone could give me a quick breakdown to make my mind 'click', i would be extremely grateful.
Thanks.
The short answer is you shouldn't worry about when an object gets deallocated (unless you are debugging a memory management problem). You should just worry about ensuring that if your code retains, copies or inits an object, it releases or autoreleases it. By doing so you will ensure reference counts are properly maintained and hence deallocation will be managed for you.
Leave the task of deciding when to dealloc an object to the runtime. Never call dealloc directly unless you are calling the super classes dealloc method at the end of your objects dealloc method.
Also, don't even look at the retain count property of an object. Various pieces of the framework manipulate those too during the lifetime of the object, and you'll see that number move around seemingly at random. It'll just drive you nuts.
The really important thing is to make sure you've got the objects retained that would be a problem if they went away suddenly, and released when you're okay with them going away suddenly.
aViewController=[[AViewController alloc]init];retainCount is 1
[self.window addsubview aViewController.view];retainCount is 2 (adding the view increments the retainCount)
[aViewController release];retain count decrements to 1;
[aViewController removeFromSuperView];retain count decrements to 0;
Now the dealloc method will be called the allocated memory will be freed. This is what have understood please correct me if i am wrong i always find difficulties during memory management.
What should I do when my app recieves a memory warning?
It all depends on your app, usually you don't have to do anything special except following Apple's recommended practices.
ViewControllers which are not visible at the moment will get didReceiveMemoryWarning message. By default (calling [super didReceiveMemoryWarning]) controller's view is unloaded (released, freed). As the view is unloading, view controller receives viewDidUnload where you should release all your IBOutlets (or otherwise retained UI elements). Only then the view can completely be deallocated and memory freed.
In the didReceiveMemoryWarning you should also free as much data as you can - if you store some part of data model in ViewController, release it, and reconstruct in viewDidLoad that would be called when your view is loaded again (when user navigates back to this controller). You can inform your model classes to free memory too.
It really depends on your app.
If your app downloads and caches lots of contents from Internet for example, you should purge as much as possible when receiving a warning.
If your app is an OpenGL game, you might have a texture/sound/data manager which references some unused data, which you then want to free. Cocos2D manages this kind of things.
If your app isn't memory intensive, you have a memory leak somewhere, and you should 1) read the Memory Management Programming Guide by Apple 2) use Instruments/Leaks.
In didReceiveMemoryWarning, you should release any cached or non-essential items to prevent running out of memory completely.
If you log or write to any other file, there might be an issue with "disk" space.
Also you should check for memory leaks.
So I have several viewControllers, each creates images using "imageWithContentsOfFile" in order to conserve memory and then sets objects to nil and releases them in the dealloc method. There are no memory leaks. The problem is memory still builds up when switching views. So for example I'll be in view1 and it'll be using 8MB of memory and then I'll switch to view2 and back to view1 again and it'll be now using 10MB of memory. I've checked allocations in instruments and it's the images using it. Is there something I need to do to flush the memory out or something?
Thanks in advance!
Shouldn't you be calling [object release] before setting object = nil?
Sorry, I'm at home and I don't have a mac here so I can't test what happens when you do it the other way around.
Also, by saying there are no leaks, did you check using the Leaks tool? I don't think the tool detects all leaks, as I've tried putting a leak on purpose but Leaks wasn't able to see it.
Whenever I add a new viewController my ObjectAlloc jumps up really high and never comes back down. Even after calling removeFromSuperview. Is this normal?
if((UIButton *) sender == gameArcadeBtn) {
GameArcade *gameArcadeController = [[GameArcade alloc]
initWithNibName:#"GameArcade" bundle:nil];
self.gameArcade = gameArcadeController;
[gameArcadeController release];
[self.view insertSubview:gameArcadeController.view atIndex:1];
}
Instantiating a view always creates many objects.As long as this view is in memory or has not been autoreleased, the objects will remained alloced in memory. Thus, to answer your question, this is normal.
It sounds like you are worried about memory usage and while it is important to watch the object allocs so that it doesn't get too it is more important to find your app leaks.
Some memory management tips:
1) do lazy loading. Only load your views when the user asks for them, not all at the beginning of the app
2) remove everything that you possibly can when you dont need it anymore. This means doing tons of work in viewWillAppear and viewDidDisappear
3) learn about #properties and how it relates to autoreleasing, and do not use properties for everything.
4) As appealing as it is, avoid autorelease and manually release objects when you dont need them anymore.
that's probably due to the fact that you're still retaining the view's controller in the class. try releasing that