|Apr 8, 2009, 05:10 AM||#1|
My first iPhone app is almost ready to ship, just a bit more bug fixing and a little bit of tax admin to finish off.
I know that this has probably been done to death but my main problem in completing development seems to be my app's memory usage. When I use instruments, I seem to have leaks here and there and eventually my app tends to crash. At the moment, it crashes too often and I can't seem to stem the problem. The app is a productivity app based on UIKit, so it's not as if it's an intensive game or anything. Plus, none of my table views generally get above 20-30 rows.
I do use UIImage's imageNamed: method quite a bit, which I've heard rumours that it has a leak in it. Can anyone confirm that? Is there an easy alternative to use instead?
I'm pretty sure I've released everything that I've alloc'd, retained or copied in my code but I think this is still an issue.
My other question relates to the didReceiveMemoryWarning methods. Currently, I've not implemented anything on my app delegate or any of my view controllers because I'm not sure how to use it. However, i've inserted an alert view that pops up whenever the app delegate method is called and I get it quite often. Does anyone know how many times your app is allowed to receive this before it crashes? I'm not quite sure how I can release memory at these points.
Any comments or pointers would be appreciated.
|Apr 8, 2009, 05:19 AM||#2|
Leaks is crap, try Clang:
It's a static analyzer but a very good one. To run against your build, something like:
xcodebuild clean && ~/Desktop/checker-*/scan-build -analyze-headers -v -v -V xcodebuild -sdk iphoneos2.2
Someone's also ported Valgrind, which is a bit more hassle to set up but will cover everything:
|Apr 8, 2009, 05:23 AM||#3|
If you don't want/need this behaviour then use imageWithContentsOfFile: or similar, which don't have this caching behavior.
|Apr 8, 2009, 05:30 AM||#4|
I think the message is pretty much a warning - 'you are using too much memory and do something about it'. If you do something about reducing your footprint then great. If you don't... well you were warned.
|Apr 8, 2009, 05:30 AM||#5|
(Apologies for multiple posts, tackling as separate questions.)
didReceiveMemoryWarning will fire when you're running low on memory to allow you to release any you don't need in order to prevent running out. Any views you're not currently viewing will then be unloaded to save memory. After this, if there is still not enough free memory, your app will be killed.
|Apr 9, 2009, 03:20 AM||#6|
UIImage imageNamed: is evil!
Thanks for your help. I now understand how the memory warnings work. It turns out that the culprit was in fact UIImage's imageNamed method. The caching behaviour is what I want, as I have a few images that are used on every table view cell.
However, it appears that there are two major bugs in the imageNamed method which can cause an app with relatively few images to run into major and terminal memory problems.
1) imageNamed seems to cache all images used for the duration of the app with no manual ability to control or empty the cache. This means that even if you have released an image and even the view and view controller that contains it, it will still hang on to the image in memory indefinitely, even in low memory situations.
However, it gets worse:
2) it appears to keep adding images to its cache, even when all images have been loaded, such that memory usage goes up and up and up.
I found that my memory problems all disappeared after I converted all imageNamed calls to initWithContentsOfFile:. However, that method doesn't cache the images and, despite having no memory problems from then on, my table view scrolling was unacceptably slow (predictably).
The solution was to implement my own image caching system, which is based on some code in this brilliant article.
Basically, I created a simple method in my app delegate called cacheImage: (NSString *)filename, which looks in an NSMutableDictionary called imageCache (initialised in the applicationDidFinishLaunching and set with an arbitary capacity - I found that 20 worked well for my app but it may depend on the amount of/size of images you have) to see if the image has already been cached and return that, otherwise initWithContentsOfFile and add to the dictionary. The keys are the filenames. To call it just replace all imageNamed calls with [appDelegate cacheImage:@"filename"]
The best bit about the above is that you can then empty this cache at any time in the applicationDidReceiveMemoryWarning method simply by calling [imageCache removeAllObjects] and the cache empties. Works like a charm.
On another note I noticed that the view controllers only release their views in low memory conditions if the loadView method is implemented. I haven't done this but may no longer need to since the above modification fixes all my crashes and improves performance massively.
jnic - I'm going to give that a go as it sounds good from what I've read.
|Thread Tools||Search this Thread|
|thread||Thread Starter||Forum||Replies||Last Post|
|Memory Issues||Hombrelobo||iPhone||3||Jan 5, 2014 02:24 PM|
|iPhone 5 Memory Issues ;(||angelwings||iPhone||7||May 7, 2013 12:27 PM|
|Memory issues||jlrathke||Mac Basics and Help||2||Jan 20, 2013 12:11 PM|
|Memory issues||martva||Mac Pro||2||Sep 4, 2012 07:51 AM|
|Mac memory issues||Cyrid||Mac Basics and Help||3||Aug 21, 2012 06:49 PM|
All times are GMT -5. The time now is 07:58 PM.