0

My code is as follows:

@IBAction func clicked(_ sender: Any) {
        let ref = Database.database().reference()
        let pass = password.text
        var firpass = ""
        var bool = false;
        ref.child(name.text as! String).child("password").observeSingleEvent(of: .value, with: { dataSnapshot in
          firpass = dataSnapshot.value as! String
            if firpass == pass {
                bool = true
                print("in here")
            }
        })
        print(bool)
        if bool {
            self.sendname = name.text!
            let vc = DatabaseTableViewController(nibName: "DatabaseTableViewController", bundle: nil)
            vc.finalName = self.sendname
            navigationController?.pushViewController(vc, animated: true)
            performSegue(withIdentifier: "username", sender: self)
        } else {
            let alert = UIAlertController(title: "Error", message: "Incorrect username or password", preferredStyle: UIAlertController.Style.alert)
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
    }

"in here" gets printed, but bool is never printed and the alert is showing. Why does my code not enter the if bool block and output the alert?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Satya Vejus
  • 313
  • 1
  • 3
  • 11
  • You are calling `async` function in which you are changing the `bool` value but you are printing outside that function, can you check is that correct? – Sohil R. Memon Jan 13 '20 at 04:00

2 Answers2

0

Data is loaded from Firebase asynchronously, since it may take a while. Instead of making your app wait for the data (which would be a bad user experience), your main code continues while the data is being loaded, and then once the data is available your closure is called.

This explains the behavior you're seeing: by the time your runs, the hasn't run yet.

the solution is as simple as it is initially confusing and annoying: any code that needs the data from the database must be inside the closure, or be called from there.

So for example:

ref.child(name.text as! String).child("password").observeSingleEvent(of: .value, with: { dataSnapshot in
  firpass = dataSnapshot.value as! String
    if firpass == pass {
        bool = true
        print("in here")
    }
    print(bool)
    if bool {
        self.sendname = name.text!
        let vc = DatabaseTableViewController(nibName: "DatabaseTableViewController", bundle: nil)
        vc.finalName = self.sendname
        navigationController?.pushViewController(vc, animated: true)
        performSegue(withIdentifier: "username", sender: self)
    } else {
        let alert = UIAlertController(title: "Error", message: "Incorrect username or password", preferredStyle: UIAlertController.Style.alert)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
        self.present(alert, animated: true, completion: nil)
    }
})

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks, that worked for the correct password, but when i put the wrong password, it still took me to the next page, and i got the following message: `Warning: Attempt to present on which is already presenting `. How do I fix this? – Satya Vejus Jan 13 '20 at 04:36
0

Also you have to set variable bool to false when you are navigating to next view controller after login. So that you login again and if password is wrong then you can not navigate to next page and only it shows alert for wrong password.

Kishan Bhatiya
  • 2,175
  • 8
  • 14