why is viewdidunload function not called when i click back button on navigation based app - objective-c

Hi I want to release my fetchedResultsController.
I was wondering why is viewdidunload not called when i push back button on navigation based application.or i should release it somewhere else?
thanks for help

-viewDidUnload is only guaranteed to be called when the view is purged from memory, and the UIKit framework might be hanging on to it in order to present the view quickly if the user goes back there. To deterministically release your fetched result controller when the view disappears, use -viewWillDisappear: or -viewDidDisappear:.

If you think that you're having leaks because viewDidLoad isn't called, than check your controller.view removeFromSuperView calls and ensure that you're using removeFromParentViewController. Instead of just removing the view from superview remove your viewController from its parentController.

I'm seeing something strange happening in my case: dealloc is called but viewDidUnload don't.
But I think I can live with that for memory management purposes because all my strong properties will be deallocated at that time (I'm using ARC).
In your case I think you should check also for dealloc being called and release your fetchedResultsController there.

you can call it yourself from -dealloc.

Related

Putting stuff in my view controller's viewDidUnload doesn't have any effect

There's a UIViewController method -(void)viewDidUnload. I tried putting NSLog("unloaded"); in there to see when the view is unloaded, but nothing was printed to the console.
Where do I put my code, so that before a view unloads I can perform an action?
If you read the viewDidUnload documentation, you see that it's related to low memory conditions and may be called to help with that. There is also a viewWillUnload that get's called before the view is released. It's also related to low memory.
If you're only interested in when the view is no longer seen, there are will/did disappear methods.
Are you using storyboard or not?
Have you tried any of this methods
-(void) viewWillUnload{}
or
-(void)viewWillDisappear:(BOOL)animated{}
If you are using storyboards the one that will that usually performs is viewWillDisappear.

Interface Builder sets control outlets to nil -- why?

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

UIViewController does not release its views

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.

Memory leak autorelease crash

When I try to switch views from A to B, everything works. But when I want to go back from B to A the app crashes?
When I remove the autorelease the app works fine but then it leaks.
Here is the code for switching the views:
-(IBAction)switchToExplainView:(id)sender{
explainViewController = [[ExplainViewController alloc]
initWithNibName:#"ExplainViewController"
bundle:nil];
[self.view addSubview:explainViewController.view];
}
You have to consider both the controller and the view.
The controller will hold on to its view, but you need to hold on to that controller. If you (auto)release it, it may easily get deallocated, and if you try to access it, your app will crash.
The view itself will be released by it's superview, but not the controller.
One possible solution is to store that controller in an ivar of your class that manages (switches) the views. Only release them when you are done with them.
Are you using a navigation controller to switch back and forth between views? If yes, you may want to use the [myNavController pushViewController:... animated:...] message. After that, you can easily release your explainViewController.

How does NSViewController avoid bindings memory leak? [have sample app]

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?