In my project, I am having an outlet for navigation controller. This works perfectly in general, but whenever my app receives memory warning, it creates a new object of root view controller class, that is assigned to the navigation controller through interface builder. After this event, two objects of root view controller resides in the memory and events gets fired twice. This is creating a mess in my case. Can you please suggest me a solution to this problem?
release the member variables, in viewDidUnload method which is called whenever the memory warning occurs. dealloc is not called so u need to release in viewDidUnload.
hope this helps.. happy coding :)
Related
I am relatively new to iOS development so appreciate your help in finding out the root cause for the error that I encountered.
I tried to debug the error using Instruments (i.e. Allocations-Zombie Profiler) but I could not make sense of the call stacks that were presented.
This is how the user interfaces are linked:
TabBarController -> NavigationController -> TopPlacesTableViewController -> RecentPhotosTableViewController -> PhotoViewController
The error occurs when I click on the Back button in the last view (i.e. that of the PhotoViewController). This action is supposed to show the previous RecentPhotosTableViewController but instead an unknown deallocated object was accessed, sometime in between the events of viewWillAppear and ViewDidAppear.
Additionally, I have a GenericTableViewController which is the parent of TopPlacesTableViewController and RecentPhotosTableViewController. The children set a NSMutableArray property in the parent which is the data that gets loaded in the children's views.
I am currently using iOS6 and XCode4.5.
[Update: In the Console, this line was shown - "[UIView _forgetDependentConstraint:]: message sent to deallocated instance xxx"].
I feel you are not using ARC, and you are not retaining of passing your previous object. In the meantime the previous object is released and then you accessing it.
Either you can refactor your code to use ARC or put retain or autorelease.
Go to Product > edit scheme >Diagnostics tap then check on enable Zombie objects
make a break point and go step by step to know which object is deallocated, it perhaps the pointer to your object has been removed then the OS has deallocated your object.
Using xcode 4.2 for iPhone app, without ARC ---
When I create an outlet using the interface builder xcode adds two lines of code to my viewController. One in viewDidUnload: -- [self setMyOutlet:nil] and second in dealloc -- [myOutlet release].
I understand the latter (the release). But why set the outlet to nil in viewDidUnload. Doesn't viewDidUnload get called before dealloc and won't setting the outlet to nil negate the release operation in dealloc? Setting to nil makes sense I would think for building a Mac application which is using garbage collection -- but it doesn't make sense for an iPhone app.
Why does the interface builder do this? Should I delete the lines which set the outlets to nil?
viewDidUnload may be called and may be not called. It depends on the current memory usage. dealloc is a place where you should clean all your properties (like arrays, custom objects). In viewDidUnload you clean views and perhaps objects created to support the view. viewDidUnload mean that your view is unloaded (but not whole view controller) and it may be created and loaded again (in viewDidLoad, of course) in the future.
Why to nil - Objective-C Difference between setting nil and
releasing
Understanding How Views Are Loaded and
Unloaded
viewDidUnload is not called everytime before a dealloc, see what the apple docs say..
When a low-memory condition occurs and the current view controller’s
views are not needed, the system may opt to remove those views from
memory. This method is called after the view controller’s view has
been released and is your chance to perform any final cleanup. If your
view controller stores separate references to the view or its
subviews, you should use this method to release those references. You
can also use this method to remove references to any objects that you
created to support the view but that are no longer needed now that the
view is gone. You should not use this method to release user data or
any other information that cannot be easily recreated.
so the idea behind it is too release any unwanted objects which can be created easily.
Now coming to the part where it sets the properties to nil.. it does so because this way you release all the memory and set the objects to nil (thus bringing your down your memory usage) and after this if a dealloc is called your app will not crash as in objective-c you can send release messages to nil objects..
I would advise you to read the apple ViewController Programming Guide , it will clear a lot of your questions.... hoping this clears some of the air.. :D
I was trying to fix a memory leak in my application and stumbled upon a very interesting thing. Now i'm not sure if there's a bug that i made somewhere or simply misuse of the technology so i'll try to get things clear with your help. Here's what happens:
i create a custom uiviewcontroller that loads its view from nib file
i release the controller
controller's dealloc method gets called where i release a custom view that i've specifically added to the view hierarchy as an outlet (i made a retainable property out of it). It has a dealloc method with a call to nslog.
the main view in the nib file (connected to controller's view outlet) is also a subclass of a uiview which also has a call to nslog in its dealloc
The problem is - even though the uiviewcontroller's dealloc is getting called, neither the main view nor the child (the one with outlet) gets released (their NSLogs don't fire).
Is it normal that this happens? Maybe iOS doesn't release the views right away? Or should i start looking for bugs in the code? If so - what could be the most probable causes?
Thanks for reading
The problem with late night debugging is that you don't consider even the simplest angles. Since i like to know how things work and do everything from scratch, i've created my own system for switching view controllers. The problem was that even though i used to deallocate the view controller when needed, i forgot to remove it from superview, thus having one more retain too many. Now there's a leak somewhere else, but i'm sure i'll solve it myself. Thanks for your comments.
I'm trying to implement my own version of NSViewController (for backwards compatibility), and I've hit a problem with bindings: Since bindings retain their target, I have a retain circle whenever I bind through File's owner.
So I thought I'd just explicitly remove my view from its superview and release the top level objects, and that would take care of the bindings, because my controller isn't holding on to the views anymore, so they release me and I can go away. But for some reason, my view controller still doesn't get released. Here's a sample app exhibiting the problem:
http://dl.dropbox.com/u/34351/BindingsLeak.zip
Build it, launch it, and hit Cmd-K ("Create Nib" in "Edit" menu) to load a NIB into the empty window. Hit Cmd-K again to release the first view controller (TestNibOwner) and load a new one. The old view controller never gets dealloced, though.
Remove the "value" binding on the checkbox, and it gets released just fine.
If you set breakpoints at the release/retain/autorelease overrides, you see that _NSBindingInfo retains the TestNibOwner, but never releases it in the leaking case.
Anyone know how to fix this?
Doing a little investigation with class-dump and friends, it looks like Apple has a private class called NSAutounbinder that takes care of this dirty work for classes such as NSViewController and NSWindowController. Can't really tell how it works or how to replicate it though.
So, I can't really answer your question on how to prevent the retain cycle from happening for arbitrary bindings in a loaded nib, but perhaps it's some consolation to know that Apple is cheating, and you're not missing anything obvious. :-)
One thing I've done for the same problem is to create a proxy NSObjectController inside my nib. My NSViewController-like class has a pointer to this proxy and all bindings are bound through it. When I want to cleanup the view controller, I then do [selfProxy setContent:nil] on the object controller and release the view controller. In this instance the NSObjectController proxy acts as the auto-unbinder in this case.
It's more manual and you can't just release the view by itself, but it does solve the retain problem.
I'd suggest you do this:
-(void) releaseTopLevelObjects
{
// Unbind the object controller's content by setting it to nil.
[selfProxy setContent:nil];
NSLog( #"topLevelObjects = %#", topLevelObjects );
[topLevelObjects release];
topLevelObjects = nil;
}
In your nib, bindings would happen through a path like:
selfProxy.content.representedObject.fooValue
When you remove your view from its superview, are you also sending it another -release message? It was created by unarchiving from the nib, right?
Working on cs193p (stanford online videos of iphone programming), I am working on Presence1 exercise
I am trying to change a UIView which is a subview of another view dynamically.
For those of you who are not aware of the assignment posted on the course, Basically the architecture of the app is as follows:
Nav Controller -> (Root) View Controller - (VC)1 for 1st screen -> calls Detail View controller VC2 for next screen
Now 1st screen has images and text that I want to load dynamically from my model (which is an object I instantiate in App delegate before pushing the 1st VC on navigation stack. I have defined a parameter in initWithNibName method to pass this model object while initializing the nib for VC1. And I also try to set the image from the model over here and in viewDidLoad and viewDidAppear methods. Its not working.
When I debugged, I saw that the model object being passed is empty.
If you understand the problem, please lemme know what am I missing.
I can post the code if required but will have to post the whole thing to make any sense.
Nailed - I was releasing my model object when not required - I was creating a "reference" to one of my objects present in the model (array containing a list of objects) . Note - I was not creating a new object by using alloc/copy. I was then releasing it (even though after the push on to the navigation stack) - Obviously causing my object memory space to get cleared and that reflected in my view controller that was receiving that model object as a parameter in its init method. This was giving the illusion that the object is not getting passed to the view controller!
Lesson Learned earlier - Be very mindful about releasing objects.
Lesson Learned Today - Be very cautious when releasing objects. Don't over release objects - make sure you are releasing an object only if you are calling alloc/copy or retaining it explicitly - memory management 101 - revisited :)
Thanks all for not replying to this question. In a way it forced me to scrutinize my code at a very micro level and I am sure I wont forget this for rest of my life! :)