Passing data to a specific ViewController - ios

The picture is just an example...
So basically I want to pass data from RED to BLUE but i have to go through GREEN.. is there a way to just pass the data straight to BLUE without it having to go through GREEN?
What I'm doing now is the conventional method of passing the data to GREEN then having GREEN read it and pass it on to BLUE
But my app has a lot of ViewControllers and I wish to be able to pass it straight to the final page (BLUE page) is there a way? Sorry I'm new to the Swift

If you try to pass data from _Red to _Blue, without _Green - it about bad architecture, becouse if something changed in logic of app, and you need to changed flow of controllers - you will feel a lot of headache...
You can wrap your data in object and pass through or you can make DataController which will be manage your data, and your ViewController's will be get\set it by Datacontroller interface

Use a simple swift class e.g Sharedclass to set a variable and then get the value of the variable from the same Sharedclass. Example is given below
import Foundation
class SharedClass {
static let sharedInstance = SharedClass()
var phoneNumber = ""
}
To set the variable
SharedClass.sharedInstance.phoneNumber = "123456"
To get the variable
BLUEViewController.phoneNumber = SharedClass.sharedInstance.phoneNumber

You can push your navigationController directly to one of your viewControllers. Try this;
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let blueController = storyboard.instantiateViewController(withIdentifier: "BlueViewController") as? BluewViewController {
blueController.passedData = passedData
navigationController?.pushViewController(blueController, animated: true)
}
Or you can just present it too. Instead of pushing in navigation controller.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let blueController = storyboard.instantiateViewController(withIdentifier: "BlueViewController") as? BluewViewController {
blueController.passedData = passedData
present(blueController, animated: true, completion: nil)
}

Related

passing data from 2 view controllers without segue

I have a mainviewcontroller and a popup view controller which opens without a segue.
the popup viewcontroller recive data from Firebase, and then i need to append this data to an array in the mainviewcontroller.
How can i do that?
(i tried to create a property of the popupviewcontroller in the mainviewcontroller, but in crashes the app)
this is the code that opens the popup:
#IBAction func showPopUp(_ sender: Any) {
let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "sbPopUp") as! PopUpViewController
self.addChild(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParent: self)
You need to connect the classes so that the popup class knows what to do with the data once it has been received. Here's a sample structure that works in a playground that you should be able to apply to your real classes.
class MainClass {
func showPopUp() {
let popOverVC = PopUpClass()
popOverVC.update = addToArray
popOverVC.receivedData()
}
func addToArray() {
print("Adding")
}
}
class PopUpClass {
var update: (()->())?
func receivedData() {
if let updateFunction = update {
updateFunction()
}
}
}
let main = MainClass()
main.showPopUp()
Or you could create a global variable so it can be accessed anywhere. ... It is better to pass data but I just thought it would be easier in this instance, so the variable can be accessed anywhere in your entire project.
if it is just a notification, you can show it in an alert, but if you don't want to use an alert my offer to present another view controller is not like this , try my code :
//if you have navigation controller ->
let vc = self.storyboard?.instantiateViewController(
withIdentifier: "storyboadrID") as! yourViewController
self.navigationController?.pushViewController(vc, animated: true)
//if you don't use navigation controller ->
let VC1 = self.storyboard!.instantiateViewController(withIdentifier: "storyboadrID") as! yourViewController
self.present(VC1, animated:true, completion: nil)
also if you want to pass any data or parameter to destination view controller you can put it like this before presenting your view controller :
VC1.textView.text = "test"

Get value from JSON and pass to another view

I've to get value from my JSON and pass this string to a variable in the second View. So, my problem it's not get value from JSON because I did it. How I can do it. I've just tried prepare (for segue) and other code but any of thats worked. Do you have an advice for me?
I hope I have been clearer. Sorry.
1) First
2) Second
This should do it.
let mainStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "Your Home View Controller identifier") as! SecondView
homeViewController.title = self.title
homeViewController.description = self.description
self.navigationController?.pushViewController(homeViewController, animated: true)

How to get data from dashboard to table view controller

I would like to pass data from a server to my table view. In the example above, there are three screens. I pass information I get from the QR code to my last screen. I send information from the two input fields to a server. How can I pass the data from my server to a table view?
There are many ways to do this. First you will have to make the request to your server. You can either use a 3rd party library like Alamofire, or a built in framework.
Then you need to pass that data into your other view controller.
Let's say your second view controller class is defined like so.
class SecondViewController: UITableViewController {
var myData: [String] = [String]()
//...
Then you can display the view controller using the following code.
//Display view controller
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let secondViewController: SecondViewController = mainStoryboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
secondViewController.myData = myData
self.present(secondViewController, animated: false, completion: nil)
Notice the secondViewController.myData = myData which is passing myData into that second view controller so that you can use it within that scope.
Then in your viewDidLoad of your table view controller you can read the data from myData and display it accordingly.
You might need to change the type of myData in your SecondViewController depending on the type of data you are getting from your server.

Setting Init VC in App Delegate?

I am trying to init my core data stack with the init VC of my app. To do this I want to pass the core data manager i have created into the first VC upon loading.
I thought this code would make sense to pass the coredatamanager into the VC, however I get errors whichever way i write this code, im sure im missing something simple?
// Initialize Storyboard
let storyboard = UIStoryboard(name: "RoutineController", bundle: Bundle.main)
// Instantiate Initial View Controller
if let viewController = storyboard.instantiateInitialViewController() as? ViewController {
// Configure View Controller
viewController.coreDataManager = coreDataManager
// Set Root View Controller
window?.rootViewController = viewController
}
Error is simply:
Use of undeclared type 'ViewController'
However if i delete 'as? ViewController' I get an error on the following line that viewController has no property coreDataManager.
Is there some sort of delegate i need to define in the viewdidload of the view controller in sending to?
EDIT Revised my code to correct the storyboard ID, however the code inside the {} doesnt seem to execute, i get the printed error i wrote due to the if let failing, so this still isnt the right way to set the viewController...any ideas as to why?
// Initialize Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate Initial View Controller
if let viewController = storyboard.instantiateInitialViewController() as? RoutineController {
// Configure View Controller
print("SENDING THIS INFO TO THE FIRST VC \(self.coreDataManager)")
viewController.coreDataManager = self.coreDataManager
// Set Root View Controller
window?.rootViewController = viewController
} else {
print("WE COULDNT SET VIEWCONTROLLER AS THE DESIGNATED VC SO MOC WASNT PASSED")
}
This is your problem:
as? ViewController
should be
as! UIViewController
alternatively this should also work:
as! RoutineController
Select the RoutineController in your storyboard and set the storyboard ID
Then use the Storyboard ID here:
if let viewController = storyboard.instantiateViewController(withIdentifier: "<storyboardID>") as? RoutineController {
The solution was that you need to define an identifier in the if let viewController to find it successfully, the working code is as follows:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let viewController = storyboard.instantiateViewController(withIdentifier: "TabBarController") as? TabBarController {
viewController.coreDataManager = self.coreDataManager
window?.rootViewController = viewController

How would I have one view controller access a variable from another view controller?

Everything I've seen on stack is passing the data from an input, onto another view controller on a button press. Let's say I have var banana that is an array of dictionaries, but once my function in ViewA.swift is done loading up banana, I want another viewController, say ViewB.swift to manipulate that data as it sees fit. I do NOT have a segue going from one view controller to the other.
EDIT: It's actually two TableViewControllers****
I've looked into NSNotificationCenter, but that doesn't seem to work with my variable type, which is an array of dictionaries
Use NSNotificationCenter for accessing data.
Try Below code
//Sent notification
let dictionary = ["key":"value"]
NSNotificationCenter.defaultCenter().postNotificationName("passData", object: nil, userInfo: dictionary)
//Receive notification
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"myMethod:", name: "passData", object: nil)
//Receive notification method
func myMethod(notification: NSNotification){
print("data: \(notification.userInfo!["key"])")
Without using segue, you can instantiate the View controller, and set the public parameteres.
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! ViewB
/* Here you have the reference to the view, so you can set the parameters*/
vc.parameterInViewB = banana
/* At this point you can present the view to the user.*/
self.presentViewController(vc, animated: true, completion: nil)
Make sure that you have given all ViewControllers an identifier, then instantiate them with:
guard let viewControllerB = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerB") as? ViewControllerB else {
fatalError(); return
}
// then access the variable/property of ViewControllerB
viewControllerB.banana = whatEver
Added for clarification
This one works for me.
Just make sure that you have given the TableViewController an identifier otherwise you will not be able to instantiate it. Also make sure that you cast the result of instantiateViewControllerWithIdentifier to your TableViewController class otherwise you won't be able to access it's variables (I've seen that you were struggling with this; if you get an error that UIViewController doesn't have a member "myArray" then you probably have forgotten to cast the result)
class TableViewController: UITableViewController {
var myArray = [String]()
}
class ViewController: UIViewController {
func someEventWillTriggerThisFunction() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let tableViewController = storyboard.instantiateViewControllerWithIdentifier("TableViewController") as? TableViewController else {
fatalError(); return
}
tableViewController.myArray = ["Value1", "Value2", "Value3"]
/* if you want to present the ViewController use this: */
self.presentViewController(tableViewController, animated: true, completion: nil)
}
}

Resources