Is didReceiveMemoryWarning / viewDidUnload called when a view controller is shown? - objective-c

A question about didReceiveMemoryWarning / viewDidUnload.
If my app has many view controllers, one of them is shown, and the others back (because of I use a navigation controller or tab bar controller, it does not matter), which view controllers will receive didReceiveMemoryWarning / viewDidUnload, all of them, only hidden, or only shown?
Is it possible that shown VC receives didReceiveMemoryWarning but not viewDidUnload (because as is shown, it doesn't make any sense).
By the way, I have these questions after seeing this diagram:
Thanks a lot for help.

First, there are two methods didReceiveMemwarnings:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
is called when the application receives a memory warning from the system.
and UIViewController's
- (void)didReceiveMemoryWarning
Sent to the view controller when the application receives a memory warning.
Second, firstly is called the code in these methods(well, of course), then in those controllers which don't have superviews(i.e those which are not displayed at the moment) the view is deleted and viewDidUnload is sent

When a memory warning is received, it is received at application level, all your viewControllers and appdelegate receives it.
It is not necessary that viewDidUnload is called for any or all controllers. It is strictly dependent on how critical OS thinks that memory warning is. Like first time - your app receives a Level 1 warning then Level 2 and most likely at third time (in short interval) OS will terminate the application believing it has gone to unstable state.

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.

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

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.

What message is sent to a UIView when the application terminates?

I am trying to locate a message which I can override and then save changes to my application.
On MainWindow.xib I have placed a UIView and set its class (in interface builder) to be my Custom view TouchDrawView.
In TouchDrawView I have a bunch of code for handling touch events and 2 arrays which track these touch events.
My application is launched by the AppDelegate but it has no reference to this TouchDrawView. It simply launches the application.
What I want to do is save my 2 arrays when the application terminates - I can do this in the TouchDrawView but I don't know what message this UIView gets sent when the whole application is about to terminate and I can't do it in the AppDelegate because it doesn't have a reference to the 2 array or the custom UIView
UIView instances will not get send any messages when the app will terminate.
There's another easy way to get notified of app state changes: notifications. You can register for notifications sent through [NSNotificationCenter defaultCenter].
For older versions of iPhone OS there's a UIApplicationWillTerminateNotification. Beginning from iOS 4 you should also listen for UIApplicationDidEnterBackgroundNotification, to prepare for termination.
The short, unhelpful answer is that a UIView is not sent a message when the application terminates.
You need to think in terms of Model-View-Controller because that's how Cocoa and Cocoa Touch are designed. Of those three, if a message was directly sent to any it would be the controller. In your case that would be the UIViewController that talks to your view.
The bad news is there is no such message there either.
An application shuts down, not an individual screen/view.
There are (at least) two ways of doing what you want to do. Firstly, you could save the state of the view controller when it is released. (That kind of feels wrong to me.)
They way that I do it in my app is to listen for the applicationWillTerminate message in your UIApplicationDelegate and traverse the view hierarchy and save the state of each view controller. When the system starts up you can do the opposite. I blogged about it here.