1

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?

1
  • When a user is using your app, do they get to SignUpViewController by segueing from the LoginViewController? If yes, it sounds like you want to pass data back to the LoginViewController. I would use a delegate to do this. You could also look into using an unwind segue Commented Jun 29, 2016 at 15:30

2 Answers 2

4

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
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

This is an interesting idea. Thank you. I may actually use this method throughout the rest of the app!
No problem! Glad I could help :)
I tried it. In the first viewcontroller presented it won't be called the function (your "userDidSignUp"). Any suggestion?
@LorenzoNeri, i tried and it needed to add class LoginViewController: UIViewController, SignUpDelegate
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.