i've a navigation controller with several viewController and tableViewController.
I'm using all autorelease objects, the problem is that when i push a new view and i use it, memory from Instrumets increase of a bigger value of memory released when i come back in the navigationController. There's not leak warning, when i return to the view then, memory will not increase again, it's like if was all in cache.
I've tried also using objects own by me, with alloc....and release but the story is the same. Is it normal?
UIViewControllers (or to be exact, views/resources/xibs associated with them) are interesting since iOS will hold on to the resources in memory and unload them as required. This is why often the dealloc method will seem like it's never called. However don't worry, if you did proper memory management, your controllers and resources will be freed up as required - if there's a low memory warning sent to your app, all the views that are hidden or have been popped, will be unloaded and dealloc'ed.
Try testing your app again, just like you did before, but this time emulate low memory usage (can be done in simulator from the Hardware menu), then see if memory usage drops due to your controllers being freed up by the system
Related
How can I track down abandoned memory if in Xcode Instruments don´t show my custom classes?
So I can see the heap is growing after I perform an action with my app (open a view and go back to the previous in my case) and I could fix some memory issues before by tracking down my mistakes in my code.
Now however, I only see things like in Generation N (= Heapshot N), non-object and I don´t know any more how I can fix the leaks. The responsible caller (not seen in the screenshots) also show no own classes/objects.
Edit
The Showing View is a UIWebView. I searched the web and found rumors that UIWebView doesnt properly releasing data. Could that be the issue? I can´t find any solution.
UIWebView is notorious for causing memory issues.
Make sure you set the UIWebView object's delegate property to nil if you assigned an object to it as documented in the class reference. You can do this in dealloc.
Cleanup the web view in viewWillDisappear:animated: by stopping URL loading with a call to stopLoading and/or setting the HTML string to nil by calling loadHTMLString:baseURL: to workaround any memory being held.
I am new to ios development. I am having a very serious issue now. My application is almost complete but it crashes very often due to memory warning. The memory warning is received whenever I present a new view controller on the top of the existing view controller. The custom view class adds UIWebView to its view when the new view controller is loaded.
I tried to debug the memory allocation with instruments but do not have any idea on how the memory is being allocated. The screenshot of the heapshot analysis shows bunch of non-objects as in the figure below and when I see the stack trace it points to adding the webview.
Please suggest me how I have to debug. What does these non-objects point to and how should I deal with them. I thank you for your suggestion and help in advance.
Non-object allocations are almost always used as backing stores within objects. I.e. an NSMutableArray will often be backed by several malloc()'d buffers that show up in non-object allocations in instruments.
Unless the non-objects are the only thing showing up as allocations in Instruments, you can ignore them.
Instead, focus on allocations of a specific type. Anything else in that Heapshot iteration? Looks like there is a CardScrollView in that backtrace on the right. Are they going away correctly?
I am working on an iPad (only) app and I stumbled across a weird problem. The app gets terminated after a memory warning on iPad 1 but works fine on iPad 2.
I am using ARC and targeting iOS 5. I use nibs and most of my assets are displayed using UIImageViews. I also have a few hundred buttons and plenty of gesture recognizers... I re-watched the WWDC11 videos (sessions 323 and 322) on ARC and I don't seem to be doing anything special.
The app is UIImage intensive, I am doing lots of animations using UIImage. I am however using the initWithContentsOfFile constructor rather than the imageNamed call. I'm trying to prevent the images from being cached by the system.
I'm also using GCD to schedule sound effects and to animate views. I'm always doing this on the main thread.
The app uses a UINavigationController that never has more than 1 UIViewController on it's stack. I can confirm that this is true because the didReceiveMemoryWarning only gets called on the current view controller (I'm logging the call).
The thing I don't understand is why Instruments is reporting high numbers (as if the view controllers don't get deallocated) in both the Allocations and VM Tracker instruments. The Allocations instrument shows a small drop when I navigate from one view controller to another (which is what I expect) but the VM Tracker Instrument shows that the Dirty Size is not dropping when I do the same thing. Eventually the app uses too much memory and gets terminated (on iPad 1). When I get memory warnings on the iPad 2 the app does NOT get terminated though...
It feels as if my images, sounds or views don't get destroyed and the memory does not get reclaimed... My object hierarchy is very basic and there should not be any retain cycles of any sort. I don't even have simple delegates...
Do you have any suggestions? I really don't want to release this app only for the iPad 2 or newer... It's an app for kids and it would be a pitty... I'd be so much happier to learn that I'm doing something wrong, as I really want to make sure this app is the best it can be...
Cheers,
Nick
There are ways to say, 'optimise' your objects by setting their properties to nil when certain things aren't needed -- so while you can't write a dealloc method anymore, you can do self.object = nil (when pertinent) which ends up doing something like this in a non-ARC world for an 'retain' (i.e., strong) property:
- (void)setObject:(id)newObject
{
[object release]; // send release message to current object
object = newObject; // set reference to newObject
[object retain]; // send retain message to newObject
}
Now while in ARC you don't/can't write retain/release yourself in your code, the compiler inserts these calls for you, meaning that in practise, setting a property to nil would do this in the above example:
[object release]; // send release message to current object
object = nil; // set reference to nil
[object retain]; // send retain message to nil (no effect)
Moreover, this is just the tip of the iceberg -- you should make sure that there are no retain cycles in your code, which could be resulting in objects leaking without recourse to their destruction. This means, that there may be places where you're using strong references to a property (i.e., an object), when you should be using a weak property. The difference being, that strong references are retained, and weak references are assigned, the former having its retainCount incremented and the latter resulting in a property assignment that looks like this if handwritten:
- (void)setObject:(id)newObject
{
object = newObject;
}
I don't like answering my own question but I figured it could be helpful to future googlers. I implemented my own UIImage based animation and I no longer use the animationImages property. Turns out my memory issues are now gone as I no longer need to store all the images in memory and I load them as they are required using a timer.
I actually think that rolling out a custom animation is beneficial since it allows for callbacks and more powerful customisation options.
Once I'm happy with it and I feel like it's ready to be shared I will post the class(es) on GitHub.
I'm working on a kiosk style slideshow app. I have a UIScrollView which shows the slides, and a factory class, which generates the slides. The "slides" themselves are UIViewController subclasses, which are loaded out from XIB files and customized by the factory class. In my main view controller, I set up the scroll view and start a timer. The timer calls a "reload" method every N seconds, which handles the reload and call to the factory class.
The method that the factory class uses looks something like this:
- (SlideViewController *)slideFromManagedObject:(Slide *)managedObject{
NSInteger slideType = [managedObject slideType];
switch(slideType){
case kSlideTypeA:
{
//
// configure arguments here
//
return [[SlideViewController alloc] initWithArgument:argument] autorelease];
break;
}
//
// More types here...
//
default:
break;
}
}
I haven't yet gotten to the point of defining all of my cases, but the ones that are filled out seem to cause jumps in memory usage. If I add return [[[UIViewController alloc] init] autorelease]; right before the switch/case, I get no visible view, as expected, but I also don't see those memory increases. I'm not sure, but I suspect that it's the "C blocks" that I'm wrapping my slide generation code in.
Some things to note:
When the app starts, I see the memory plateau from about 400 kilobytes to around double that. Then, when the slides progress, any of the slides whose generation code is contained in curly braces is called, the memory plateaus upwards again.
This behavior only seems to happen once per launch - when the app loops through all of the slides, the plateaus to_not_ happen again. However if the app is backgrounded and then relaunched, the plateaus do occur again, consuming even more memory.
When I left the app to run overnight, for about 10 hours and forty minutes, the memory usage had slowly climbed from about 1.44 megabytes to somewhere closer to 1.57 megabytes. I suspect that there are/were some other leaks in there that may have been fixed by my tweaking, but the main jump from about 800 kilobytes to somewhere between 1.4 and 1.5 megabytes is still an issue.
Instruments does not report any leaks, but the plateauing concerns me.
What could be causing the increased memory?
EDIT:
So I don't think it's the blocks, since using an if/else seems to do the same thing.
Here's a screenshot of the Allocations instrument running:
Where could possibly be holding on to these views?
One possible explanation for what you are seeing is some caching that UIKit (I assume) is doing of your objects (don't know what they are, but I think of images mostly).
Caching is often used during transitions and for other internalities of UIKit.
UIKit empties its caches usually when a memory warning is received, so you could try and send one to see what happens. In actuality, I suspect that results of sending a memory warning will not be very easy to analyze, since all of your views are also unloaded, hence memory will go down forcibly. But you can try...
As to how sending a memory warning to the device (as opposed to the simulator), here you find an useful S.O. post.
I'm getting strange memory allocations from core iOS libraries, seen in Instruments Allocations (Malloc 1.00KB) which continually rise and result in app crash (iPad).
The app allows the user to browse through articles (body in webview, title/author/date in labels) - the problem occurring as each new view controller is loaded (previous view controllers are released/deallocating - this isn't the problem).
The following CoreGraphics allocations only happen when the .text property is set for the UILabel:
CoreGraphics "CGGLyphBitmapCreate", "CGFontSetStrikeValue" - sometimes one or both of these shows 6 or 7 times (1KB each) but at least one of each every time view loads.
In addition to this, Foundation "[NSNotificationCenter addObserver:selector:name:object:]" sometimes appears, sometimes not, sometimes up to 6/7 times on one load. I understand why adding observes this might allocate some memory, but surely deallocating view controller with "[NSNotificationCenter removeObserver:self] should remove all references again.
I've included screenshots from Instruments... won't even address the WebCore and libcache.dylib allocations that **sometimes show up on load. Very confused here too.
Did you track leaks? As long as it doesn't leak memory you normally don't have to worry.
Maybe you have a thread without an autorelease pool set up? If this is the case, and an autorelease object is created, e.g. by a getter method, the object cannot be retained by an autorelease pool since it does not exist, and it will leak.
So it your app is multithreaded, make sure that every thread has an #autoreleasepool{} block that covers most of the thread code.