ViewDidLoad wont fire after pushed to new viewcontroller - ios

So I am trying to get from one viewcontroller to another using the push segue (selected in the storyboard). When I arrive at the second viewcontroller, the viewDidLoad is not firing! Is that a bug or am I doing everything wrong?

It really hard to give suggestion to this kind of question,
Double check below things once.
Is Storyboard View-controller has the Class as the SecondViewController.h
Is the 'View' connected to the outlet as the Seccndviewcontrooler's View.
Performing segue are you sure pushing the SecondViewcontroller only.
Clean build the proj once.
just run the app - Place a NSLog Statment in right after the [super viewDidLoad] and see is that printing logs in console.
try keeping a breakpoint or NSLog at viewWillAppear/viewdidAppear.

What do you mean by pushed to new view? ViewControllers can be pushed not View. ViewDidLoad will be fired only when a ViewController is loaded into the memory. It can also be fired if the VC was unloaded by iOS runtime and is being loaded again.
But thumb rule is that it will fire only when the VC is being loaded not afterwards. Please elaborate your question further if I am interpreting you incorrectly.

Related

Does viewDidLoad get called more than once in UITabBarController?

I'm using SWRevealViewController in my app (to get the slide out side panel) however whenever the user navigates to another viewController like 'settings' and comes back, everything gets reset. I understand this is normal behaviour for storyboards since a new VC is instantiated and viewDidLoad is called each time. I tried to get around this by storing the VC in an array in the AppDelegate and then going back to the original viewController, this prevented viewDidLoad being called when the original VC is initially re-presented but I still found it get's called randomly when moving between veiwcontroller's, resetting all my properties etc.. On researching, the Apple documentation does say not to assume viewDidLoad will only be called once.
Is this behaviour apparent in UITabBarController when switching tabs as I'm thinking of ditching the SWRevealViewController and using that instead if it's going to be less headache.
Should I be handling this differently, ie. storing the 'state' in NSUserDefaults and restoring on viewDidLoad?
Thanks in advance.
viewDidLoad is called exactly once, when the UIViewController is first loaded into memory. This is where you want to instantiate any instance variables and build any UIViews that live for the entire lifecycle of this UIViewController.
In UITabBarController also the viewdidLoad for UIViewController is called once, when you are switching tabs.
viewDidLoad() method is called only once. Its an integral part of the cycle.
It is called then the respective UIViewController class is loaded into memory.
And yes, if you want to initialise any properties or access and modify the NSUserDefaults, it can and should be done in the viewDidLoad method.
As for your app, whenever the user will switch between different UIViewControllers, the viewDidLoad method will be called for every destination UIViewController.
Also, as correctly pointed out, it'll also be called in the case of a memory warning.

App running slow after loading viewcontroller, then unload about 15-20 times

Using:
Xcode 4.6
Storyboards
ARC
Model segue to SecondViewController
I have an app that has the main ViewController that loads a new veiwController when the device is rotated to the right. When the app starts everything works great. If I rotate the device, then back which unloads the secondview controller, about 15-20 times the app is very slugish. I have narrowed down that it only happenes when the seconed view controller is loaded and only when i rotate the device a nunmber of times. I also have narrowed down that is is a memory issue. I installed an app that keeps track of the memory used and available. My memory goes from 400mb to 900mb used when i rotate the device a number of times. I am trying to give as much info as I can. Each view has 8 NSTimers that fire every second.
Is there a way to programmatic unload a view, to make sure is is being unloaded?
I have included this code to ensure the loading and unloading:
`- (void)setView:(UIView *)aView
{
NSLog(#">>> Entering %s <<<", PRETTY_FUNCTION);
if (!aView) // view is being set to nil
{
NSLog(#"Should be unloading now");
}
[super setView:aView];
NSLog(#"<<< Leaving %s >>>", __PRETTY_FUNCTION__);
}
log result:
2013-04-22 16:42:03.588 xxxxxxxx[xxxxxxx] >>> Entering -[GraphViewController setView:] <<<
2013-04-22 16:42:03.589 xxxxxxxx[xxxxxxx] <<< Leaving -[GraphViewController setView:] >>>
`
I am not sure what I need to be looking at to correct this.
Any "points" in the right direction will be very appreciated .
Thanks
You haven't given much information about how you "unload" SecondViewController. Are you doing a modal segue to it as well? If so, that's your problem -- every time you do a segue, you instantiate a new view controller, and if these are modal segues, the presented controller has a strong pointer to the presenting controller, so none of these controllers will ever get deallocated as you go back and forth.
As a rule, you should never go backwards in a storyboard using anything but an unwind segue. So, the solution to your problem is to use an unwind segue to go from SecondViewController back to MainViewController -- this will actually go back to the same instance of MainViewController that you came from, and SecondViewController will be deallocated. If you don't know how to make an unwind segue, I will edit my answer to show you how.
After Edit:
To make an unwind segues, you do two things. In the controller that you're going back to, you add a method -- the two important things are that it be an IBAction, and that it has a single argument that's typed to UIStoryboardSegue*. It doesn't matter what you call it, and it doesn't even need to have any code inside it, though I usually put in a log statement just to be sure it's called. Then, in IB in the controller you're unwinding from, you control drag from your UI element like a button or table view cell (or from the controller itself if you want to fire it from code), down to the green Exit icon at the bottom of the scene -- it's important to note that you are dragging from a UI element to the exit icon in the same controller, not between controllers. When you let go of the drag over the exit icon, you will see any methods you created with the signature I mentioned above. Choose the one you want, and that's it. You can implement prepareForSegue in the source controller just like any other segue if you want to pass any information back to the destination controller.

IOS - Help understanding Storyboards - Why rootViewController keeps getting reloaded?

Googled all over but no luck thus far. Before I started using Storyboards, I had a couple applications that used multiple viewcontrollers. When going back to a certain viewController (by dismissing a child viewcontroller), I'd find my original (or root) viewcontroller intact.
Now that I'm trying storyboards, it seems my rootViewController gets reloaded from time to time, loosing all data and restarting fresh from viewDidLoad. I think this happens between transitions from one view controller to another. For example, from the rootViewController, I present another view controller. As I dismiss those other view controller to return to the rootViewController, it looks reloaded and fresh new. It only happens sometimes, maybe when the OS issues memory warning. I noticed all variables in my rootViewController are reset and viewDidLoad is executed again (confirmed with NSLog).
Is this normal?
From all tutorials I've seen, they say if using Storyboards to leave the delegate method "applicationDidFinishLaunchingWithOPtions" pretty much intact (whereas in my older application I'd do some viewcontroller alloc here.
I've tried the following, unsuccessfully:
// in didFinishLaunchingWithOptions of delegate.m
[self.window.rootViewController retain]
did not work. My main viewController still gets released/reloaded from time to time
// in my viewDidLoad of viewcontroller.m
[self retain];
Didn't work either
Do I have to declare and allocate the viewController in my delegate file, and then assign it to rootViewController? I tried something like that but crashed, maybe not doing it right.
Thanks?

Segues and viewDidLoad/viewDidUnload method

I am making simple storyboard application which has 2 UIViewControllers and I am switching between them by using modal segue. Each UIViewController has one UIButton which is used to perform segue to another UIViewController. In viewDidLoad method I animate appearance of that UIButton on each UIViewController. I am using Cross Dissolve Modal segue.
When I press UIButton on 1st UIViewController I navigate to second UIViewController and animation is executed and 2nd UIViewController is shown. After I press UIButton on 2nd UIView Controller, first UIViewController is shown and it's animation is executed. Everything looks fine and viewDidLoad methods are called for each UIViewController when ever I navigate to it. And that's great.
I tried now to change Modal segue type from Cross Dissolve to other two by default offered in XCode Interface Builder. I changed to Cover Vertical, and everything worked just fine, without changes. But when I tried Flip Horizontal Modal segue, I saw a problem.
When performing Flip Horizontal Modal segue, my UIButton on both UIViewControllers is shown, but animation isn't executed. I tried debugging and I am sure that animation commands are being executed, but animation isn't shown.
So that's my first question: Does anyone know is there any difference between these types of Modal segues which may cause my animation not showing up?
Other questions are related to basic theory of segues and memory management. When I perform segue and navigate to some UIViewController, viewDidLoad method is called every time. So, does that mean I created new object instance each time viewDidLoad method was executed?
I also notice that viewDidUnload method is never called. So, if answer to previous question is affirmative (each viewDidLoad execution creates new object instance), does that mean that my UIViewController object instances are never being unloaded and deleted? Or ARC is doing garbage collection behind the scenes?
If someone could explain how things works with storyboard segues and memory management/object lifecycle and why viewDidUnload method is never being called, I'd be very grateful.
[edit #1: Trying to unload UIViewController after performing modal segue]
[update #1: This shouldn't be done, viewDidUnload will be called automatically]
I am making segue in IBAction attached to UIButton click. I have written this peace of code to perform modal segue.
#try
{
[self performSegueWithIdentifier:segueToPerform sender:self];
}
#catch (NSException *exception)
{
NSLog(#"Exception: %#", exception);
}
#finally
{
[self viewDidUnload];
}
I have manually called viewDidUnload in #finally block and I have checked weather viewDidUnload is called in runtime and yes - it is called.
Does this mean I managed to unload my UIViewController object I created when navigating to it with modal segue from another UIViewController and remove it from memory?
Is this method regular as a replacement for:
[self dismissViewControllerAnimated:YES completion:nil];
because this above line returns me to UIViewController from which I navigated to current UIViewController, but that doesn't fit my needs, because I need to perform new segues from current UIViewController to other UIViewControllers (beside returning back to UIViewController from which I navigated to current one)?
[edit #2: Finish]
At the end I changed implementation model and loaded new UIViews under single UIViewController after I created separate XIB files for those UIViews. I have marked answer from #dasblinkenlight as the right one since it contains lots of useful informations and discussion on that answer gives good answers to some doubts about using modal segues.
I do not know the answer to the first part of your question, but once you learn the answer to the second part, I am sure that you would go with a different solution anyway.
viewDidLoad method is called every time. So, does that mean I created new object instance each time viewDidLoad method was executed?
Absolutely. "Modal" segue causes the new view to obscure the old one completely until the new view is closed. If you go back and forth many times, your code will accumulate a whole "stack" of views underneath the current one.
I also notice that viewDidUnload method is never called. So, if answer to previous question is affirmative (each viewDidLoad execution creates new object instance), does that mean that my UIViewController object instances are never being unloaded and deleted?
This is correct, all the view controllers that you create are still there, ready for you to close the views on top of it.
Or ARC is doing garbage collection behind the scenes?
ARC is not a garbage collector, it is a reference counting mechanism with a little automation from the compiler. The objects are still there.
You should change your code to call
[self dismissModalViewControllerAnimated:YES];
in the second controller, rather than using a modal segue that brings you back to the first one.
I hit a similar issue where I had a complex VC navigation web, and the resulting use of segues (no UINavigationController) was sucking up too much memory.
You may want to take a look at this question/answer to see my final solution.
The conversation here between uerceg and dasblinkenlight helped me in finding this solution.
Segues and clearing historical ViewControllers from memory

ViewController viewDidLoad after presentModalView called?

I have a viewController called "FirstViewController". In an IBAction i call another ViewController called "thePageFlipViewController" and push it in sight via
[self presentModalViewController:thePageFlipViewController animated:YES];
after some time the user closes thePageFlipViewController with a button where the following code is executed via a delegate in FirstViewController:
[self dismissModalViewControllerAnimated:YES];
[thePageFlipViewController release];
And here is my problem:
-viewDidLoadin FirstViewController get's sometimes called after dismissing thePageFlipController. I don't understand why, because firstViewController should live in background. Is it dependent how long the modal view is displayed? is it possible that ARC does release something?
My problem is, that i initialise a lot of objects in viewDidLoad and the app crashes if viewDidLoad gets called again. I define some Routes for RESTKit there and RestKit complains that the routes are already set up and crash the app.
Any Help is appreciated.
When a view is not actually displayed it can be unloaded to free up memory. You would get a call to viewDidUnload: when that happens so you can release any objects you are holding strong references to. Then next time the view is needed, viewDidLoad: will get called again when the view is reloaded, there you have to recreate the objects you released in viewDidUnload:.
See the Memory Management section of the UIViewController class reference.
Also this answer has a good explanation already.

Resources