ViewdidLoad called every time - ios

Why every time I change UIViewController embed in UINavigationController using show push in storyboard ViewDidLoad is called?
It hasn't to be called only once or I have to check programmatically if it is already loaded?
Another relative question:
In the following best practices found here in StackOverflow that user are talking about init method, but if my ViewController are loaded by storyboard where I have to initialise my properties?
Best practices
Remember not to do view controller initialisation in viewDidLoad. This is a common mistake. For stuff that should only happen once when the view controller is loaded, do it in one of the controller's init methods.

viewDidLoad is called first time when the viewController's view is loaded, (either by accessing the view controller's view or by presenting a view controller via modal presentation or via a push presentation). Once the view controller is loaded, viewDidLoad will not get called again. If you want to use init method, you need to use initWithCoder for the things that are from storyboard.

Related

In iOS, does a segue instantiate the new-to-be-used view controller? Or is it already instantiated?

So for instance, let's say I have a regular subclass of UIViewController and I have connected a control object contained within this controller's view to a segue action that will let another view controller's view come into view...
Simple enough.
When I call the method called prepare(for:sender:) on the regular subclassed UIViewController, at this point, I'm concerned with the new to be used view controller whose view will pop on the screen.. Is this new view controller already instantiated somewhere?
I believe the answer is yes because inside the prepare(for:sender:) function, I set a reference for segue.destination (which is the destination view controller) and when I print that reference, it seems to be a place in memory already which tells me that the new view controller is already instantiated.
Can anyone confirm/deny that this new view controller (created from the storyboard) already has been instantiated, or put this in simpler terms?
Thanks
Apple's documentation says,
When the storyboard runtime detects a custom segue, it creates a new instance of your class, configures it with the view controller objects, asks the view controller source to prepare for the segue, and then performs the segue.
( https://developer.apple.com/reference/uikit/uistoryboardsegue )
So the destination UIViewController is instantiated by the segue just before sending prepareForSegue to the source UIViewController.
So to answer your questions directly, it is "yes" to both questions:
In iOS, does a segue instantiate the new-to-be-used view controller?
Yes, the segue does instantiate the destination view controller.
Or is it already instantiated?
Yes, by the time your prepareForSegue is called, it is already instantiated - immediately beforehand.
UPDATE: As #Jeffery_Thomas commented, this is trivially easy to demonstrate by adding an NSLog() line to your destination view controller's init.
Can anyone confirm/deny that this new view controller (created from the storyboard) already has been instantiated,
Yes. That is what it means to trigger a segue. A triggered segue's job is to instantiate the destination view controller, and prepare exists so that you can configure that instance.

Calling a view controller class without popping up the view controller itself

I am upgrading my app version, hence needed to reduce two view controllers to one. Hence, I am calling the second view controller skipping the first one. But here I need to call the class of first view controller as there are some important declarations and implementations. How can I call first view controller's class without popping up its view controller.
This is confusing.
Why not taking all the initializing code from your first VC (copy-paste your properties, initialization in viewDidLoad etc.) to your second VC ?
Once you are done, get rid of the first VC as it is useless and make your second view controller the root.
A ViewController is meant to be "viewed", I suggest you don't just hide it, that's a really bad architecture.
If you don't need one view controller at all, then you can delete that View Controller from storyBoard, and also subclass your class as an NSObject class (lets call it DataProviderClass) instead of previously( UIViewController) subClass. It isn't a good idea to have a "dummy" view controller in a navigation Stack.
You can use your DataProviderClass class as a support file that can provide any data to your Second View Controller. And to perform calculations/methods in this class before launching your second VC, just run these methods in viewdidLoad method, by creating an instance of this NSObject class (DataProviderClass) and keeping a reference to it.
When you segue further, you can very easily even transfer the same reference of DataProviderClass.

self.navigationController is nil during state restoration

After implementing state restoration in my app I am having difficulty with my view controllers.
My issue is that in viewDidLoad of the view controller I am attempting to restore the self.naigationController property, which is nil.
I have set breakpoints in the viewDidLoad method of each view controller that comes before the one I am trying to restore. In the first view controller, the navigation controller is found. In every one after that, including the one I am trying to restore, the navigation controller is nil.
This is causing bugs where I cannot set the navigation bar visibility, views are misplaced, etc.
Does anyone have an idea why this might be?
Try moving the code to viewWillAppear.
Unlike viewDidLoad, viewWillAppear can get called multiple times, so take care to make sure your code is idempotent. That is, make sure the results are what you expect if the method is called repeatedly. For example, make sure you don't initialize a new subview if the view has already been added.
The navigationController property searches up the parentViewControllers to find one of class UINavigationController. Only view controllers loaded from the storyboard can find their navigation controller at the viewDidLoad time (and in awakeFromNib). It is likely you are instantiating a new instance of the view controller during the restore process rather than using the one that was created by the storyboard. The solution is either to help the restore process find the existing view controller if it has changed paths e.g. because of split controller orientation change (via viewControllerForRestorationPathComponents in your app delegate) although that comes with its own set of issues, or make your view controller work by not requiring the nav controller in the viewDidLoad, e.g. put it in the viewWillAppear as others have suggested.

How to instantiate a particular view controller with storyboard in iOS at early stage of loading?

When using tabs with storyboard in iOS 5, some of them may take quite a long time to initialize when switching to it (for example, a tab containing GLKViewController).
This happens because an amount of work in viewDidLoad method in this controller could be very big.
Is there a way to initialize particular view controller (and call it's viewDidLoad method) defined in the storyboard at early stage - when an application starts? Having done this, the delay should be eliminated.
Are you sure it's the view controller's instantiation and not the viewDidLoad method? The view controllers are probably all created when the storyboard is unpacked, but a view controller tries to delay loading its actual view object as long as possible; viewDidLoad isn't called until the view property of your UIViewController subclass is accessed.
So a way around this could be to manually access the view property:
__unused CGRect frame = [[tabBarController.viewControllers objectAtIndex:index] view].frame;
If the slowdown is, in fact, in the instantiation and the view controller isn't being created until you switch to that tab, then you'll have do force the view controller to be instantiated by accessing it programmatically, like in the above example.
Calling the frame of the vewcontroller or the .view property will most likely work,
but i dont advice you to mess up with the viewcontroller initializations and view settings
For the following reasons
changes you make will not be standard, they will be tricks and hacks that will later on get out of hand
changes that you make will not be carried with you easily to other projects you create
If i faced a problem like this i would create the GLKViewController separately for example in the app delegate and held it there, untill the viewDidLoad gets called in the viewController, then i would move this initilized GLKViewController to the viewController

How does a segue create the destination ViewController?

As the question suggests: how does a segue create the destination controller? To be specific, which method gets called? I want to init another ViewController from a nib when a segue creates him. How do I accomplish that?
Thanks a lot
Short answer: initWithCoder: is called.
Longer answer (from apple's docs on UIViewController):
If your app uses a storyboard to define a view controller and its
associated views, your app never initializes objects of that class
directly. Instead, view controllers are either instantiated by the
storyboard—either automatically by iOS when a segue is triggered or
programmatically when your app calls the storyboard object’s
instantiateViewControllerWithIdentifier: method. When instantiating a
view controller from a storyboard, iOS initializes the new view
controller by calling its initWithCoder: method instead. iOS
automatically sets the nibName property to a nib file stored inside
the storyboard.

Resources