Joesoes Joesoes - 3 months ago 20
Swift Question

ViewController segue and login

I'm new to Swift (and programming in general). I'm having some difficulties in Xcode with the login feature. What I want is that the user should be logged in if no errors was returned and the user should be sent to another controller. I've read some of the documentation from Apple and the performSegueWithIdentifier (and of course some questions asked here), but it still does not work when I use a segue with push or modal that are given an identifier. Either the app crashes, or the user is sent to my UITabBarController even if the credentials was incorrect. This is my LogInViewController.swift

@IBAction func loginAction(sender: AnyObject)
{
if self.emailField.text == "" || self.passwordField.text == ""
{
let alertController = UIAlertController(title: "Oops!", message: "Please enter an email and password.", preferredStyle: .Alert)

let defaultAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alertController.addAction(defaultAction)

self.presentViewController(alertController, animated: true, completion: nil)
}
else
{
FIRAuth.auth()?.signInWithEmail(self.emailField.text!, password: self.passwordField.text!) { (user, error) in

if error == nil
{
self.emailField.text = ""
self.passwordField.text = ""
}
else
{
let alertController = UIAlertController(title: "Oops!", message: error?.localizedDescription, preferredStyle: .Alert)

let defaultAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alertController.addAction(defaultAction)

self.presentViewController(alertController, animated: true, completion: nil)
}
// User Logged in
self.performSegueWithIdentifier("LoggedIn", sender: self)
}
}
}


The error I get in the console:

2016-09-04 14:55:30.019 DrinkApp[37777:1006336] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'LoggedIn'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'

Answer

Here is a Firebase login example:

  func login() {
        FIRAuth.auth()?.signInWithEmail(textFieldLoginEmail.text!, password: textFieldLoginPassword.text!) { (user, error) in
            if error != nil {
                let alert = UIAlertController(title: "User Authentication error",
                                              message: error?.localizedDescription,
                                              preferredStyle: .Alert)
                let OKAction = UIAlertAction(title: "OK",
                                             style: .Default) { (action: UIAlertAction!) -> Void in
                }
                let resetPasswordAction = UIAlertAction(title: "OK",
                                                        style: .Default) { (action: UIAlertAction!) -> Void in
                }
                alert.addAction(OKAction)
                guard let errorCode = FIRAuthErrorCode(rawValue: (error?.code)!) else { return }
                switch errorCode {
                case .ErrorCodeWrongPassword:
                    alert.addAction(resetPasswordAction)
                case .ErrorCodeNetworkError:
                    print("Network error")
                default:
                    print("Other error\n")
                    break
                }
                self.presentViewController(alert, animated: true, completion: nil)
            } else { // User Logged in
                self.performSegueWithIdentifier("MySegue", sender: self)
            }
        }
    }

I only handled two errors for this example.

If you use push segue, you need to have navigation controller, and your root segue should lead to the login view controller, then another segue to the next view controller. This last segue must have an identifier (in this case it's MySegue)

Edit: Since it seems that your problem is not with Firebase, but with setting up the storyboard. Here is an example:

  1. Set up one UINavigationController two UIViewControllers
  2. Control Drag between the UINavigationController to the middle UIViewControllers and choose root view controller from the popup menu
  3. Control Drag between the UIViewController to the last UIViewControllers and choose show
  4. select the segue added in the previous step and change its identifier (in the attributes inspector) to MySegue. 5.Choose the Middle UIViewControllers and change the class name (in the identity inspector) to your login view controller class.

Here is the full setup: full setup

control drag menu (step 2): step 2

Segue's attributes inspector (step 4): step4