Akash Savediya
Akash Savediya

Reputation: 11

How to transfer data between view controller using segues

I'm trying to pass data using a prepare(for segue:) function but it's showing nil in the second VC. Am I doing anything wrong?

class ViewController: UIViewController {

    var first : [String] = []

    @IBOutlet weak var passField: UITextField!
    @IBOutlet weak var userID: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func login(_ sender: Any) {
        let user : String = self.userID.text!
        let password : String = self.passField.text!

        if user != "" && password != "" {
            let postString = ["username":user, “password”: password]
            var request = URLRequest(url:URL(string:"http://mydomainhere.com/api/login")!)
            request.httpMethod = "POST"
            request.httpBody = try! JSONSerialization.data(withJSONObject: postString, options:.prettyPrinted)
            let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
                if error != nil {
                    print("error=\(error)")
                    return
                }

                do {
                    if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
                        let firstName = json["first_name"] as? String
                        let lastName = json["last_name"] as? String
                        self.first.append(firstName!) //putting into Array
                        self.performSegue(withIdentifier: "loginSegue", sender: self)
                    }
                } catch {
                    print(error)
                }
            }
        }
    }

    // data transfer to another controller
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "loginSegue" {
            let secondController = segue.destination as? SecondVC
            secondController?.name = first //passing to next VC   //* here having the issue its not passing the data to next VC
            print(first)    // here first is printing perfectly
        }
    } 
}


// second View Controller
class SecondVC: UIViewController {

    var menu_vc : MenuViewController!
    var name : [String]?    // passing to this Array

    override func viewDidLoad() {
        super.viewDidLoad()
        print(name)    // here printing nil 
    }
}

Upvotes: 0

Views: 580

Answers (2)

ciamic
ciamic

Reputation: 26

As suggested by @Sweeper, it could very well be that your destination view controller is embedded in a UINavigationViewController, hence your segue.destination is in fact a UINavigationViewController, not a SecondVC.

You can try this code:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    var destinationViewController = segue.destination
    if let navigationController = destinationViewController as? UINavigationController {
        destinationViewController = navigationController.visibleViewController ?? destinationViewController
    }
    if let secondController = destinationViewController as? SecondVC {
        secondController?.name = first
    }
}

Of course the first four lines of code could be refactored in an appropriate function (even better if in an extension of UIViewController).

If that solves the problem, you can watch cs193p Stanford iOS course for further details. In particular watch https://www.youtube.com/watch?v=HQrXM2zUPvY&index=6&list=PLPA-ayBrweUz32NSgNZdl0_QISw-f12Ai starting from the 30:20 mark.

Upvotes: 1

Maulik Pandya
Maulik Pandya

Reputation: 2230

Everything seems perfect with the below snippet

var first : [String] = []

@IBAction func btnTapped(_ sender: Any) {
    let firstName = "iOS Geek"
    self.first.append(firstName)

    self.performSegue(withIdentifier: "MovetoSecVC", sender: self)
}


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "MovetoSecVC"{

        let secVC = segue.destination as! SecondVC
        secVC.name = first
        print(first) // it'll print here ["iOS Geek"]
    }
}

// Your Second View Controller

class SecondVC: UIViewController {

var menu_vc : MenuViewController!
var name : [String]?    // passing to this Array

override func viewDidLoad() {
    super.viewDidLoad()

    print(name!)    // it'll print here ["iOS Geek"]
    }
}

Upvotes: 0

Related Questions