简体   繁体   中英

How to Transfer Data when dismissing controller view in Swift

I am working on an iOS app that logs the user in by a Login View.

There are two controllers: LognViewController and SignUpViewController If a new user signs up instead, then the Sign Up View Controller makes an API call to retrieve a new user account. Then, the Sign Up page should transfer the new User object back to the Login page, which in turn logs the user in to the main app.

Based on a previous post I like the idea of a closure, and I'm trying to implement it here; however, I'm getting a nil on the closure function variable. My code is something like this:

In the First Controller:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "userSignUp" {
        if !self.userTextField.text!.isEmpty {
            let nav = segue.destinationViewController as! UINavigationController
            let vc = nav.topViewController as! SignUpViewController
            vc.email = self.userTextField.text!
            vc.submitUser = signUpToLogIn
        }
    } 
}


// asynchronous get user back from sign up
func signUpToLogIn(currentUser: User) {
    self.currentUser = currentUser
    self.checkCurrentUser()
}

In the Second Controller:

var submitUser: ((currentUser: User) -> ())!


@IBAction func signUpButtonTapped(sender: UIButton) {

    doSignUp({(u: User?) -> () in
        if u != nil {
            self.submitUser(currentUser: u!)
            self.dismissViewControllerAnimated(false, completion: nil)
        }
    })
}

I'm looking at the debugger, and it says fatal error: unexpectedly found nil while unwrapping an Optional value When I work with a breakpoint, I can see in the variables section that the submitUser variable is always nil.

Is there a different way of doing this now?

Instead of passing a closure, can you use delegation instead? Your SignUpViewController can notify your LoginViewController when a new user has signed up and pass the new User object back through a delegate method like so

Signup View Controller:

protocol SignUpDelegate {
    func userDidSignUp(u: User)
}

class SignUpViewController: UIViewController {
    var delegate: SignUpDelegate?

    @IBAction func signUpButtonTapped(sender: UIButton) {
        // Make async call to sign new user up here
        // Once you get a User back from your API call your delegate 
        // method in your completion or at the end of your network call
        self.delegate?.userDidSignUp(newUserObject)
        self.dismissViewControllerAnimated(false, completion: nil)
    }
}

Then in your login view controller you can implement this delegate method

Login view controller:

class LoginViewController: UIViewController {

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "userSignUp" {
            if !self.userTextField.text!.isEmpty {
                let nav = segue.destinationViewController as! UINavigationController
                let vc = nav.topViewController as! SignUpViewController
                vc.email = self.userTextField.text!
                vc.delegate = self
            }
        } 
    }

    // MARK: SignUpDelegate
    func userDidSignUp(u: User) {
        // Log user in with new user
    }
}

Inside the @IBAction func signUpButtonTapped(sender: UIButton) :

Try using this function to do the transition to another view controller:

[self performSegueWithIdentifier:@"segueIdentifierHere" sender:self];

Don't forget to remove the self.dismissViewController function you are currently using before you try the performSegueWithIdentifier

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM