ViewDidLoad call only one time in time of navigation - ios

I have viewcontroller. I have created its object in appdelegate.m file as I want to use that viewcontroller in poptoviewcontroller method. Now once I have created its object in appdelegate file and when I am pushing that viewcontroller it is calling viewdidload only 1 times. But from second time it is not calling viewdidload. I have some component which i want to load each and every time that controller load. What to do?? Is there any other way to use viewcontroller in popToViewController method without creating its object in appdelegate.m file
I have 4 viewcontroller A,B,C,D.
I am navigating from A to B. And I have some component in B which I am loading in viewdidLoad. Now From A to B flow I am getting value from server of component. And displaying in B. Now if user want to change value then he will redirect to C from B to change B component value. And also some times he will redirect to D and from D I am poping to B with B component value. Now If i will write my B code in viewwillappear then When I will return from C to B it will load value which I got at the time of navigation from A to B.

You can use viewWillAppear or viewDidAppear (this last one is called after the first). ViewDidLoad is only called when the ViewController is constructed. Then, since you let it live in the navigation stack it isn't called anymore.
For more information follow this thread on stackoverflow.
EDIT
With your edit the whole question becomes a different one. If you want a delegate to be called every time you will show your ViewController viewWillAppear or viewDidAppear is the answer.
It seems to me that you are over complicating things. From what I understand you are changing B in your AppDelegate? If so I can't see any problem with B having a previous state when you came from C and update your state in viewWillAppear. If you have some kind of pointer in the AppDelegate to B and you change it, then the viewWillAppear shouldn't have any issue.
You can have several solutions for your problem, and it all depends on your specific case but I would suggest that you separate the model better. You could create a singleton that holds B data and in the viewWillAppear you can get that data and display it. Then C and D only perform changes on that singleton.

viewDidLoad Method only called on initialisation of class, If you have some task to do again and again whenever view appears on screen than use
viewWillAppear
or
viewDidAppear
Method.

Related

Understanding interaction between Swift files - how do I call from one to the other

I have my ViewController.swift which is the first to run when the app loads. I then segue to another SecondViewController.swift file.
The ViewController.swift instance is still in existence, correct?
So now, from SecondViewController.swift, I call ViewController().someFunction()
The ViewController's "viewDidLoad" does not get called, only the function I specifically called to.
Now: if I instantiate an Int variable in ViewController.swift "var testNum = 2" and in the ViewController's viewDidLoad I change its value to 14. Then I segue to SecondViewController. Then I call to ViewController().someFunction() and I print the value of testNum in that function, I get the instantiated value of 2 instead of the value that ViewController had which was 14, which leads me to believe that I've created a new copy of ViewController by calling a function in this way.
Is that right? Is that what I've done? And if so, is there a way to call a function in the existing ViewController instead of creating a new ViewController from within SecondViewController.swift?
THANKS!
I have my ViewController.swift which is the first to run when the app loads. I then segue to another SecondViewController.swift file.
Nitpicking: You don't segue between 'files', you segue between instances of classes defined in those files.
The ViewController.swift instance is still in existence, correct?
Yes. Well, the original instance of the class defined in that file, see above.
So now, from SecondViewController.swift, I call ViewController().someFunction()
The ViewController's "viewDidLoad" does not get called, only the function I specifically called to.
With ViewController() you create a new instance of the ViewController class and then directly invoke that method on it. Which doesn't make a lot of sense.
Now: if I instantiate an Int variable in ViewController.swift "var testNum = 2" and in the ViewController's viewDidLoad I change its value to 14. Then I segue to SecondViewController. Then I call to ViewController().someFunction() and I print the value of testNum in that function, I get the instantiated value of 2
When you call ViewController() you create a new instance of the class defined in the ViewController.swift. Quite (very much) likely this is not what you want to do.
It appears you rather want to hang on to the original instance of that VC. So you need to transfer that when doing the segue.
I'm sure you've read the View Controller Programming Guide for iOS, right? ;-) This is a relevant section:
The prepareForSegue:sender: method of the source view controller lets you pass data from the source view controller to the destination view controller. The UIStoryboardSegue object passed to the method contains a reference to the destination view controller along with other segue-related information.
Usually you wouldn't want to preserve a reference to the original view controller, but rather transfer relevant data from that into the VC you segue to (to decouple them).
If you're going to be storing values, I'd recommend creating a model class.
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
This will keep the data independent of the controllers because, to answer your "The ViewController.swift instance is still in existence, correct?" question, it may or may not be in existence depending on memory. That's why creating a model is desirable because then you're not worried about it.
If you'd like examples, there are many online if you google MVC iOS. Hope that helps.

What is the best way to pass values from a child ViewController to a parent ViewController in iOS?

Say you have a ViewController that segues into a child ViewController. The child ViewController needs to be prepared with some values, typically set by the parent ViewController in the prepareForSegue() function.
Now say that some value in the child ViewController is updated and should be remembered for the next time it is called. What is the best way for the child ViewController to let the parent ViewController know of the updated value, so that it can be considered in subsequent calls to prepareForSegue()?
Please elaborate on the persistence/non-persistence of your solution and common/best practices.
You can create delegate from your child ViewController. Every time your values (you want to save) update, send it to parent ViewController.
See some example about delegate in here:
http://www.raywenderlich.com/115300/swift-2-tutorial-part-3-tuples-protocols-delegates-and-table-views

Update NSUserDefaults data in one ViewController changed in other ViewController

I got two viewcontroller: MainController and OptionsController.
OptionsController it can be reached through a button from MainController.
In OptionsController is there some values that I can save with NSUserDefaults. These values are needed in MainController.
If I change these values in OptionsController when I come back to MainController they don’t change, but if I launch MainController again, these values was changed correctly.
It seems that when MainController becomes active again, after leaving OptionsController, viewDidLoad is no longer raised.
How can I update the data in MainController, please?
As rounak says, viewDidLoad is only called once in the life of a view controller. If you have code you want executed every time a view controller is shown, put it in viewWillAppear.
NSUserDefaultsis a fairly heavyweight way to pass info between in-memory objects (it writes to disk). If you don't need persistence between runs, one of the other options he suggested would be better. I'd suggest the delegate pattern or a completion block.
viewDidLoad is called only once for a view controller. You can use NSNotification, KVO, blocks or something like a delegate pattern to get a callback in your MainController whenever the value changes inside the OptionsController.
You can otherwise write code in viewWillAppear which gets called each time you pop the options controller.

how to get view controller storyboard id or restortionIdentifier in backwards navigation?

In my navigation I have a rootViewController (AController), a second ViewController (BController) and a third one (CController).
I can navigate my app by pushing A --> B --> C.
When I go back from C --> B, in BController:viewdidLoad how can I get I'm navigating from C and not from A?
I tried to use self.presentedViewController.restorationIdentifier but it always return me the identifier of AController, not the CController one.
Should I use the storyboardID property? how can I do that?
Any help is appreciated.
The best practice for such application would be to use a UINavigationController for navigation. If you are navigating using UINavigationController then viewDidLoad will only get called when you go from A to B but will not be called when you go back from C to B controller
Try using delegation to set a property in B When loading C and going back to B again.
Also, as #khawar-ali mentioned, viewDidLoad only gets called when loading the view controller for the first time hence viewDidLoad method won't get called when going back from C. Try ViewWillAppear/viewDidAppear instead? :/

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.

Resources