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.
Related
Hello i have done a page controller for my app.
This page controller will appear at the app launch if there isn't any "User" core data object on the device.
So want i want to do is :
When app launch, do a core data request that return all "User" objects in a array. (this part is ok)
If the array is empty the VC presented is the pageController else that's the normal on whose presented.
The pageController and the other controller are on different storyboards.
I have seen we can change the first storyboard in the app parameter, that's parameter is called main interface.
Actually main interface is the normal VC, so how can i present the page controller programmaticly in my didFinishLaunchingWithOptions() when my condition is true ?
Inside didFinishLaunchingWithOptions
// query coredata
if arr.isEmpty {
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "pageID") as! PageController
self.window?.rootViewController = viewController
}
else {
let otherController = UIStoryboard(name: "Other", bundle: nil).instantiateViewController(withIdentifier: "otherID") as! OtherController
self.window?.rootViewController = otherController
}
I have 2 view controller with navigation controller. First view controller has 4 text field and second view controller has 4 text field. To navigate first view controller to second I am using following code:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var destinationVC:UIViewController
destinationVC = storyboard.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC
navigationController?.show(destinationVC, sender: self)
To first from second view controller I am using
navigationController?.popViewController(animated: true)
However, even if the fields I have filled in first view controller keep the values when I go from first to second values I have written have disappear because of popviewcontroller method. What is the best way to remember values in second view controller?
You can have singleton where you can store the values as dictionary(or something else)
class Settings: NSObject {
static let shared = Settings()
public var dictionaryToStore: [String: String]?
private init() {
super.init()
}
}
And in your controller when poping
Settings.shared.dictionaryToStore = {"key1": textfield1.text, "key2": textfield2.text, ...
}
And in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
textfield1.text = Settings.shared.dictionaryToStore["key1"]
textfield2.text = Settings.shared.dictionaryToStore["key2"]
...
}
Also you can create custom object and store it.
EDIT 1 **
To have variables after app has been terminated you can save dictionary in UserDefaults
class Settings: NSObject {
static let shared = Settings()
public var dictionaryToStore: [String: String]? {
set(newValue) {
let defaults = UserDefaults.standard
defaults.set(newValue, forKey: "SomeKey")
}
get {
let defaults = UserDefaults.standard
let loadedValue = defaults.object(forKey: "SomeKey")
return loadedKey
}
}
private init() {
super.init()
}
}
The key reason for values not to be remembered on the SecondVC is that you're using new instances of SecondVC each time you open it.
So you better create an instance (first 3 lines of your code do that job) of SecondVC once, somewhere in the beginning of FirstVC, and use it in show() func everytime you need to show SecondVC instead of creating multiple instance of SecondVC each time.
In that case you'll see all values "remembered" in the SecondVC.
You can use key-value storage like NSUserDefaults in your secondViewController to save data when viewController will disappear and load on viewDidLoad. Or save your data in some struct/object instance and pass it when you push secondViewController.
if you want to pass data from you first view controller to second view
how to pass data from first viewcontroller to second viewcontroller
in above code though you are making new instance of you view controller still you can pass data by setting variable of second view controller in first view controller before
navigationController?.show(destinationVC, sender: self)
like
destnationVC.variableTOSet = valueTopass
and then
navigationController?.show(destinationVC, sender: self)
and then in second view controller use that variable to use value
so that how you can pass data from your first controller to second view controller
now if you want to pass data from your second viewController to first controller then you can use delegates
I am using Firebase email authentication in my app, I have 2 different view controllers for the sign up process, first view controller asks for the email for firebase and the second view controller asks for the password. How can I set it up for the firebase code?
if let phoneEmail = phoneEmailTextField.text, let createdpassword = createdPasswordTextField {
Auth.auth().createUser(withEmail: phoneEmail, password: createdpassword, completion: { (user, error) in
I have the textfield "phoneEmailTextField" in the first view controller (class 1) and the textfield "createdPasswordTextField" in the second view controller(class 2). How can I link the textfield "createdPasswordTextField" from the second view controller (class 2) back to the first view controller (class 1) in order to execute the Firebase function?
Use segue for passing mail textfield's data from first view controller to the second.Shortly,search how segue,navigation controller pushing works.
Something like that;
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
if let secondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController {
secondViewController.emailTextFieldString = emailTextField.text!
self.navigationController?.pushViewController(secondViewController, animated: true)
}
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)
}
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)
}
}