I am trying to follow the Apple's recommendation to handle low-memory warnings (found in Session 416 of WWDC 2009 videos) by freeing up resources used by freeing up my dataController object (referenced in my app delegate) that contains a large number of strings for read from a plist:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[_dataController release];
_dataController = nil;
NSLog([NSString stringWithFormat:#"applicationDidReceiveMemoryWarning bottom... retain count:%i", [_dataController retainCount]]);
}
But when I run ObjectAlloc within Instruments and simulate a Low-Memory Condition, I don't see a decrease in the memory used by my app even though I see the NSLog statements written out and the retain count is zero for the object. I do pass references to the app delegate around to some of the view controllers. But the code above releases the reference to the _dataController object (containing the plist data) so I would expect the memory to be freed.
Any help would be appreciated.
Are you sure that app delegate is the only owner of _dataController? -release only decreases the ref count, it won't deallocate the object unless the ref count drops to zero.
If _dataController is owned by other objects too, send a message to them to release it.
I am double-checking that. Thanks for the input! I did reread the memory management docs from Apple and I did put an NSLog statement in the dealloc method of my DataController and it is being called. I also put wrote out the retain count before the release and setting to nil of _dataController. The retain count is 1.
So this drives me back to why I am not seeing a significant decrease in memory usage. I think I need to understand the ObjectAlloc display in Instruments better and where the largest allocations of memory are taking place in my app. After searching for help in this area, I am frustrated with trying to determine from Instruments where this occurs. I can see that there is 3.54 MB for "All Allocations" and 608 MB for Malloc 32.00 KB. If I drill down on Malloc, I only see the Responsible Caller as being framework calls like png_malloc and inflateEnd. I am looking for calls within my code that is responsible for the Malloc but I don't see that. All this to say that I wonder if I am releasing the object or objects that will really make a significant difference in the amount of memory used for the low-memory condition. I think I need an in-depth tutorial for Instruments. The Apple help docs are okay but an example with code would be more helpful.
Related
I've never personally seen didReceiveMemoryWarning called before. Is there a known threshold of memory usage where it gets called?
It's called when the system has low memory, then you need to purge your UIViewController.
You can simulate a memory warning in the Simulator: Hardware > Simulate Memory Warning and see what happens.
If you are supporting prior versions to iOS6 it's important to take note of the following from Apple's documentation:
Prior to iOS 6, when a low-memory warning occurred, the
UIViewController class purged its views if it knew it could reload or
recreate them again later. If this happens, it also calls the
viewWillUnload and viewDidUnload methods to give your code a chance to
relinquish ownership of any objects that are associated with your view
hierarchy, including objects loaded from the nib file, objects created
in your viewDidLoad method, and objects created lazily at runtime and
added to the view hierarchy. On iOS 6, views are never purged and
these methods are never called. If your view controller needs to
perform specific tasks when memory is low, it should override the
didReceiveMemoryWarning method.
About the threshold, I try not to exceed 12MB of memory.
No. It is called when springboard feels that there are too many resources using memory on the device. Depending on how much stuff other apps are using on your phone, it can happen sooner or later. You can never reliably calculate or rely on when it will happen.
Also be warned, because the memory reported in tools like allocations is not necessarily correlated to the footprint of your app, so it can look like you are not using much, but you may still get this warning.
from the documentation , when the system determines that the amount of available memory is low then this method is called. system determines low memory itself , when your app allocations exceed the amount of memory available to your app then this method is called. Please refer http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
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.
How to solve memory allocation in ios ?give me the right way to solve memory issues and memory leaks.
The best way to avoid these Memory issues is through proper coding. Just go through the Apple reference on Memory Management.
You only release or autorelease
objects you own.
You take ownership of an object if you
create it using a method whose name
begins with “alloc”, “new”, “copy”, or
“mutableCopy” (for example, alloc,
newObject, or mutableCopy), or if you
send it a retain message.
You use release or autorelease to
relinquish ownership of an object.
autorelease just means “send a release
message in the future” (specifically:
when the used autorelease pool
receives a drain message—to understand
when this will be, see “Autorelease
Pools”).
Without more info all I can say is...
Release anything you init and/or alloc that is not autoreleased.
Delete anything that you call "new" on
free any data you malloc
Use Instruments to diagnose where your leaks are occuring.
Release anything you retain
release anything you init that is not autoreleased.
#Nipin, For solving memory issues, you'll have to release each object that you're allocating... ie, use [yourObject release]; for each object you call alloc method... Also, unload any textures that you're using [texturename unload];
[texturename release];
Do all these when you no longer requires those objects or textures and in most cases it can be where you exit from the scene...
follow the below link memory management
another link is small guide for quick point small article
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.
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.