Yeongchan Jeon
Yeongchan Jeon

Reputation: 519

How can I pass data to the next view controller when it is loaded programmatically?

Suppose I have three view controllers in a Main.storyboard. Two of the three, vc_login and vc_studyDesc load the other view controller using a UIButton with 'present modally' option.

The other one vc_signup has a UIButton, which may go back to the previous controller. To implement this, I used the following methods:

vc_studyDesc has an identifier of studyDesc; I let it pass its identifier to vc_signup. In the same way, vc_login has login as an identifier.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if sender as! UIButton == qnaSignUp {
        let signup = segue.destinationViewController as! vc_signup
        signup.latestVC = "studyDesc"}}

This one is in the UIViewController class for vc_signup. By referencing a string latestVC, the method determines which VC to move on.

@IBAction func backBtnClick(sender: UIButton) {
    print("latestVS: \(latestVC)")
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewControllerWithIdentifier(latestVC)
    vc.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
    print("check check")
    self.presentViewController(vc, animated: true, completion: nil)}

The problem I have is that the app gets terminated when vc_studyDesc is called by vc_signup. I found that this is because I missed a significant variable which must be loaded in vc_signup.

vc_studyDesc has some data to be referenced from Firebase when it is loaded. I did this by loading a variable postID from the prior vc to vc_studyDesc; which is vc_list.

So I just saved postID using NSUserdefaults.standardUserDefaults(). It is solved but I'm wondering if there's any way to pass data using the way I used in vc_signup.

As far as I see, I cannot find any way to pass the data into vc_studyDesc.swift; for the vc is chosen by its identifier..

Can I pass the variable I want in the way I want?? And adding tags would be appreciated!

Upvotes: 0

Views: 323

Answers (2)

Olivier Wilkinson
Olivier Wilkinson

Reputation: 2856

So there are a couple problems with this design.

When you instantiate a viewController you are creating a new instance of that class, and presenting it adds it to the stack. Think of the stack like a deck of cards, you start with one card and then add or remove them, the top card being the visible vc. When you are going back to studyDesc you are instantiating and presenting it so you will have 3 VCs in your stack, of which two are studyDesc (the one you started with and the one you add when you try to go back)

To remove a VC from the stack you can use

dismissViewController(animated: true, completion: nil)

or if you have the VCs in a navigation controller you can use

popViewControllerController(animated: true, completion: nil)

in terms of passing information between viewControllers, if the info is in the VC you use to present your new controller you can use prepareForSegue like you already have. To pass information back you should use a delegate pattern. So to implement a delegate pattern in this case you would do the following:

Declare a protocol (not inside your classes, above there but below your import's)

protocol SignUpDelegate {
    signInCompleted(infoToPass: AnyObject)
}

Then have your studyDesc class conform to this protocol and implement the function signInCompleted

StudyDescVC: UIViewController, SignUpDelegate {

    func signInCompleted(infoToPass: AnyObject) {
        // do what you want with the info here
    }

}

Then in your signUpVc add a var delegate (which will be used to call the signInCompeleted function)

class SignInVC: UIViewController {

    var delegate: SignUpDelegate!

    func finishedSigningIn() {
        delegate.signInCompleted(infoToPass: //yourinfo)
    self.dismissViewControllerAnimated(true, completion: nil)
}

And then in your prepareForSegue set the delegate

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if sender as! UIButton == qnaSignUp {
    let signup = segue.destinationViewController as! vc_signup
    signup.delegate = self
    }
}

Upvotes: 1

Asaduzzaman Shuvro
Asaduzzaman Shuvro

Reputation: 180

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewControllerWithIdentifier(latestVC) as! YOUR_VIEW_CONTROLLER_NAME
    vc.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
    vc.name = "Andrew"
    print("check check")
    self.presentViewController(vc, animated: true, completion: nil)


    //set a variale or property to your viewController

   class YOUR_VIEW_CONTROLLER_NAME: UIViewController {
    var name: String?

}

Upvotes: 0

Related Questions