UIViewController does not release memory the first time - iphone

Got the weirdest thing happening ... I have a pretty complex UIViewController subclass of which I'm loading through a NIB file.
I push the view by simply doing the following:
SecondViewController2 *secV = [[SecondViewController2 alloc] initWithNibName:#"SecondViewController2" bundle:nil];
self.secondViewController2 = secV;
[secV release];
[self.navigationController pushViewController:secondViewController2 animated:YES];
[secondViewController2 release];
secondViewController2 = nil;
As you can see I release secondViewController2.
The thing is, when I perform it the first time, ALTHOUGH dealloc method is called in secondViewController2, I still observe in instrument an additional 2MB which do not seem to get released. There are no leaks of any sort, I checked already.
When I perform the below action the the second, third, fourth time etc. the dealloc is getting called and I DO NOT OBSERVE ANY ADDITION in memory. That alone convinces me that I do not perform the error in my code since the same code is being run the first, second third time but only the first time around 2MB are not being released. As I stated dealloc for secondViewController2 is still being run!!!
Any idea? is it bug in Apple's mechanism ?

First off, it is not possible to answer thoroughly your question without analyzing your complete implementation. But, generally speaking, if I understand correctly your question, I would say that the situation you are describing is a correct one.
You should think that there are actions that definitely have a permanent effect on memory occupation.
E.g., if you load some images into memory through [UIImage imageNamed]`, then your image will also go into an image cache which will not be emptied when the class that loaded the image is deallocated. Another good example is that of a singleton: a singleton class occupies some memory the first time it is instantiated and it usually never releases it (before the program ends - and when I say singleton, read also any kind of static globals).
Those are just 2 examples, but there could be many more cases of this. And it could be done in your own code, but it could also be done by some framework that your controller uses. This effect would be more likely if your controller is the first controller you instantiate in you app that uses some kind of functionality. But basically, it cannot be known before hand, I would say, but only after inspection of your program behavior via Instruments.
The really valuable information for you is that upon successive instantiation/deallocation of you controller class, the memory occupation does not grow. Generally speaking, this is a sign of two things:
your class has no memory leaks;
your class has not abandoned memory.
What 1+2 implies is that the overall memory consumption of your program (as far as your controller is concerned) is flat. (although it has a cost that you pay on first use).
So, in my view, your issue is at most one of "optimization" of memory usage by your controller. As I said, one should know exactly what your controller does to know whether those 2MB comes from some cache, or whatever else (and in some cases it could be not under your control either).
Hope it helps.

Related

iPhone memory not released after view unloads and dealloc, why?

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 work around/handle delegation EXC_BAD_ACCESS errors? Obj C

I'm coding a library (Obj-C for iPhone) that I want to package and sell, so I obviously need to work out any design kinks before listing it for sale. I am also utilizing this library to help me develop another app.
My library is heavily built on task delegation. The primary function I have is to launch a (potentially) long-running process, and when it's done, I call a Delegate Protocol method in the class's delegate.
An additional complicating factor here is that I will often schedule this task to fire off every 30 seconds or so. Usually, I do this with [self performSelector:#selector(someMethod:) withObject:nil afterDelay:30] rather than using an NSTimer. Then, when the delegate method successfully returns, I process the returned data and trigger the method to fire in another 30 seconds. This gives me 30 seconds BETWEEN method calls, rather than 30 seconds FROM THE START OF ONE CALL TO THE NEXT. (This is mainly just in case the call ever takes more than 30 seconds, which shouldn't happen.)
The error that I'm catching is that sometimes, the Delegate callback method is failing with an EXC_BAD_ACCESS error. Based upon my investigation, it appears that the delegate of my class library has disappeared (been released/dealloced) since the long-running process was initiated. Thus, when it calls [[self Delegate] doSomeDelegateMethod], it's accessing a released object.
I tried first checking [[self Delegate] respondsToSelector:#selector(doSomeDelegateMethod)], but even that access apparently also throws the EXC_BAD_ACCESS.
It doesn't yet seem that checking for [self Delegate] == nil is the right way to go, either.
One way I think I have solved the problem, in this specific instance, is when the view controller that instantiates my object is disappearing (and therefore on its way to the garbage dump), I call [NSObject cancelPreviousPerformRequestsWithTarget:self]. This apparently fixes the problem. (Does this "fix" also indicate that my object "knows" about the call to come and keeps itself in memory until it can successfully, desperately, fire off its final shot?)
This appears to put a band-aid on a bullet wound. Yes, it appears to stop my app from breaking this time, but my gut tells me that this is a poor solution.
I've also considered setting the custom object to nil in my viewWillDisappear:animated: method, which is probably the correct coding pattern, but it doesn't seem right that the customer has to be so precise in handling my objects.
What's really bugging me, though, is that I haven't yet found a way, as a library developer, to "box in" my code so that it won't throw an exception for the user if they don't do just the right things. Basically, I'd like a way to have my object:
Get a request.
Go look for the answer.
Find the answer.
Try to return the answer.
Realize that there's nothing on the other end.
Give up and die on its own. (OK, so "die on its own" probably won't happen, but you get the point.)
One interesting side point:
A main reason I have for preventing this type of error from occurring is this:
I did the following steps:
Built my library's .h/.m files.
Generated my library's .a output file.
Imported my library's .a/.h files into another project.
Had the error described above.
Got to peruse the code from one of the .m files that SHOULD have been hidden inside the .a file.
Am I missing something here? Am I really risking exposing my entire source code if it ever throws an error for a client? (This is just a side issue, but I'm fairly concerned here!)
Thanks for any help you can provide to help me be a better programmer!
---EDIT---
I have found another reason why this is important. In another view controller, where I am using this library, I implemented the NSTimer strategy. If the view is popped from the navigation stack (i.e., in the viewWillDisappear:animated: method), I invalidate said timer. So, no more calls will go to my library after the view disappears.
Here's the rub: what if the view disappears IN THE MIDDLE of the long-running call? Yes, it's tricky and unlikely to do, but I just had it happen on the simulator. In particular, THIS is why I'm looking for a workaround to let my code realize "hey, there's nothing on the other end of this pipe" and then fail gracefully. Anyone?
Thanks!
There are several approaches to this problem:
The traditional delegate approach (UITableViewDelegate) makes it a requirement to clear yourself as delegate before going away. This is traditionally done in dealloc of the delegate with otherObject.delegate = nil. Failure to do so is a programming error. That's basically what you're seeing. This is the common pattern when the delegate and the delegator have basically the same lifespan.
Another approach is how NSURLConnection handles it: retain your delegate until you're done. The key to this working well is that NSURLConnection has a lifespan of its own, so the retain loop will work itself out automatically. UITableView could not retain its delegate because this would almost always create a permanent retain loop. If your object lives for a while and then goes away, then this makes sense. Typically here the delegate has a much shorter lifespan than the delegator, so the retain loop doesn't hurt anything.
Any object that calls performSelector:withObject:afterDelay: should always call cancelPreviousPerformRequestsWithTarget:self in its own dealloc. This has nothing to do with your delegate, though. It should be self-contained to the object itself. (I don't know why I keep thinking this is true, and then proving to myself again that it isn't. When you call performSelector:...afterDelay:, you are retained, so you can't deallocate before it fires. My SIDE NOTE, while true, isn't relevant here.)
SIDE NOTE cancelPrevious... is really expensive in my experience. If you have to call cancelPrvious... very often, I recommend keeping your own one-shot NSTimer and just resetting it when it fires to get the same effect. performSelector:withObject:afterDelay: is just a wrapper around a one-shot timer.
I'm answering myself because the page warned me to not have extended discussions in the comments... :)
OK, so it appears that part of my answer is that [self performSelector:withObject:afterDelay:] automatically retains my object until it gets to "fire that shot", at which point I'm guessing the view controller dies.
So, now it makes sense why my custom class is trying to access a released object when it tries to return its answer to its delegate, which is an __unsafe_unretained object, meaning that it can die at will (I think).
What I'd like now is a way to prevent this from causing an error. In .NET, I've got all sorts of error handling options to do this, but I'm unable to think of a fail-safe "bail out" here.
I've tried [[self Delegate] isKindOfClass:..., but can't be sure what kind of class the delegate will be, so it won't work.
I've also tried [[self Delegate] respondsToSelector:#selector(...)]. I'm not sure why this fails, but I get the EXC_BAD_ACCESS here, too.
What I don't want is my customers to be able to crash my product with such a simple, innocent mistake.
As an aside, does anyone know why this sort of failure gives me such easy access to the contents of the .m file that should be hidden inside my .a file? Did I build my library incorrectly?
Thanks!
Try setting Delegates to nil in dealloc.
example:
self.fetchedResultsController.delegate = nil;
I've seen this problem a lot lately and usually fix the problem. Even though delegates are supposed to be weak references, sometimes some private implementation is using them as well.
If I release, I get bad access, if I retain, I leak
That's where I had a similar problem.
Edit: When using ARC, you can still override dealloc for cleanup, you just can't call [super dealloc] or release anything.

Objective-C multithreading, what happens when an object gets dealloc while its methods are being executed? (And how to prevent it?)

I am writing an app for the iPhone and arrived at this situation.
I have a view controller, myViewController, that will dealloc whenever the user taps the "back" button on the screen. There a thread in the background that communicates with a remote server and may message a method, updateUI, method in myViewController.
What would happen if the background thread messages updateUI in myViewController, but the user just happened to tapped the "back" button at the right time such that it causes myViewController to dealloc while updateUI is still executing?
My guess is that the dealloc method will run and the app might crash if updateUI ends up using a null pointer. Assuming this is the case, the current solution I have is:
[self retain];
// updateUI code here
[self release];
I am unsure if this is the best solution, as I feel that this is a common problem when dealing with multiple threads.
Is my assumption correct? If so, is there a better solution?
What you are describing is known as a "race condition." Race conditions can be difficult to identify in testing, track down once reported, and reproduce because sometimes execution in the debugger can effectively modify how the code is being executed (avoiding the condition that one is trying to reproduce). Race conditions are one of the major pitfalls in concurrent programming - making the area deceptively difficult to do well.
In principle, it is a best practice to minimize the use of shared resources and closely qualify how the sharing is coordinated when implementing concurrency. If an object is shared across multiple threads, it should be retained by each of them to ensure that the object stays in-scope while each thread completes its processing.
Apple has been taking steps to simplify implementing concurrency. This is a good starting point for familiarizing yourself with the topic on iOS.
http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40008091
It's also useful to be aware that Objective-C 2.0's properties can support atomic operations (and are atomic by default, thus the nonatomic keyword to disable this default).
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html
And, this is the old-school guide to threads (out of favor approach, but still useful background - be sure to be familiar with NSLock).
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html%23//apple_ref/doc/uid/10000057i
Whenever some part of your code depends on another, it should retain this dependency until it is not needed. In your case the background worker should retain the controller and only release it when the work is done (or cancelled).
If you dealloc and then nil your objects then this shouldn't be an issue - you can send messages to nil in objective-c.
Alternatively, if you wanted the viewController to get the message and if your targeting iOs 4, you can use blocks and GCD. Blocks auto retain objects and therefore if a block references your viewController, would keep it around for as long as its needed, even if -(void)dealloc ; has been called.
Here is a decent Block tutorial
Yes, your app will crash, likely with something along the lines of EXC_BAD_ACCESS.
As far as multithreading, you will want to retain your objects until everything is done with them and program defensively. Check for the existence of objects before trying to manipulate them.

didReceiveMemoryWarning and viewDidUnload

From Apple's View Controller Programming Guide / Managing Memory Efficiently;
didReceiveMemoryWarning
Use this method to deallocate all noncritical custom data structures associated with your view controller. Although you would not use this method to release references to view objects, you might use it to release any view-related data structures that you did not already release in your viewDidUnload method. (The view objects themselves should always be released in the viewDidUnload method.)
viewDidUnload
You can use the viewDidUnload method to deallocate any data that is view-specific and that can be recreated easily enough if the view is loaded into memory again. If recreating the data might be too time-consuming, though, you do not have to release the corresponding data objects here. Instead, you should consider releasing those objects in your didReceiveMemoryWarning method.
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html
For didReceiveMemoryWarning, we are recommended to deallocate non-critical data structures. So, what is critical and what is non-critical?
Also, it says to release what we did not already release in viewDidUnload.
But when there is a memory warning didReceiveMemoryWarning is called and view could be unloaded then viewDidUnload is called. So, is it talking about the moving those codes to the former event's method(didReceiveMemoryWarning) or am i missing something about the order of events?
For viewDidUnload, we are recommended to care about easily recreating the data when reloading a view.
So, if a view is in use and could not be unloaded, why will we release time-consuming data in didReceiveMemoryWarning? After those data released, when user tries to do something within the current view, then it will be time-consuming to load them too.
First of all, these are just guidelines, so if you don't think it makes good sense to release something in didReceiveMemoryWarning then don't do it. But keep in mind that if your application is the one that is causing the memory warning in the first place then it will eventually just be terminated by the OS.
Re (1): Critical vs. non-critical is entirely your call. Only you can really determine what data you're holding that you consider critical. Though it's probably going to be closely related to your (3), that is, something that is easily recreated is probably not too critical.
Re (2): I don't think the statement is in reference to the order of the calls. As you have realized, in general, viewDidUnload is going to get called after didReceiveMemoryWarning (since didReceiveMemoryWarning can cause viewDidUnload to be called). As an example, in viewDidUnload one will release references held to UI elements from a nib. So don't also release them in didReceiveMemoryWarning.
Re (3): If a view is in use and thus can't be unloaded, then yes, obviously it doesn't necessarily make much sense to release it in didReceiveMemoryWarning. However, you may actually have instances where a view couldn't be unloaded, but is known to not be visible (not terribly normal), in which case it might make sense to unload it's data and recreate it when the view is visible once again.
Additionally, I agree the "Instead, you should consider..." remarks are a bit odd, but again I think the point of recommending the data be released in didReceiveMemoryWarning stems from the fact that if you're receiving those warnings then your own app might be in danger of being terminated. So while it is currently the case that viewDidUnload probably is always called as the result of a memory warning, that may not always be the case in the future and so conceptually it makes more sense to release the data in didReceiveMemoryWarning itself. In didReceiveMemoryWarning you KNOW there is memory pressure, in viewDidUnload you may not. So while it's true that the data will then be expensive to recreate, that might be better than having your app terminated. To the user it will appear as though the app crashed.
My own personal approach to those methods is generally this:
viewDidUnload - Release any references to UI elements loaded from a nib. Release any UI elements I created myself in viewDidLoad.
didReceiveMemoryWarning - Release any data that is used in the presentation of the UI that I can recreate if/when viewDidLoad is called again (or some other app specific event). Do NOT release anything that I can't possible recreate.
The apps I'm building are graphics-intensive, both in terms of layout chrome, and in the images associated with the data I'm downloading and displaying.
My didReceiveMemoryWarning methods are ALL about determining which images I'm holding in memory but not currently displaying, and dropping them from memory. The other piece of that is, you need to check before displaying an image whether it's still around, and lazy-load it if not.

iPhone dev - In didReceiveMemoryWarning or every time

In a multi-view application, do you think its better to let views automatically get unloaded in memory tight situations, or to actually only ever have one View Controller allocated at a time, and when you switch views, the new one is created, the old one removed, the new one adde d and the old one released. Deallocating every time also means that there is a slight delay when switching to a new tab (very slight). So What do you think?
Also, I'm a bit confused about how and when and where and by who views are released (through viewDidUnload) automatically. If someone could clarify that for me, thanks.
In general, don't unload views unless you have to (didReceiveMemoryWarning) or it makes sense (something like a login form that's unlikely going to be used again).
You can't really assume that you have a fixed amount of memory. iPhone's have less memory than iPod touches. iPhone 3GS's have more memory than either. Jail-broken handsets often have substantially less memory.
By only releasing views when you have to you're making your app run faster on the 3GS and allowing it to run when there's less memory available.
The didReceiveMemoryWarning method releases the view if it is not visible. The following is from the documentation (v3.x):
The default implementation of this
method checks to see if the view
controller can safely release its
view. This is possible if the view
itself does not have a superview and
can be reloaded either from a nib file
or using a custom loadView method. If
the view can be released, this method
releases it and calls the
viewDidUnload method.
Obviously you also need to release any cached data. SDK2.x does not have the viewDidUnload method.
Depends, if you have a bunch of Views that the user switch back on forth from often then I would say to keep those in memory at that time, if theres views where the user wont come back to for awhile then you can probably unload that viewController and save memory. However if you have views that are taking up a ton of memory each then it might be wise to unload the viewcontroller when its not in use. Its really a matter of how often you are going back to the views and how much memory the view takes, also how many views you have. Taking these things into consideration you should be able to make a good decision of when to keep the viewControllers around and when the unload them. I believe that the view is a round as long as the ViewController is around (unless u release it explictly, which might have bad side effects (dont know)) , viewdidUnload just tells you that the view was unloaded of the screen, not too sure on that point tho.