RufusV
RufusV

Reputation: 407

CloudKit, My Auth Not Working

I have made an authentication that uses records in CloudKit, so I made an account, then went to my login page and tried to login, the first time I pressed login, it showed my error message "Username or Password was Incorrect", however the second time I press the login button it works. I really have no idea what is causing this.

Here is what I believe to be the relevant code:

func loginPressed() {

    validLogin()

    if usernameExists == true && passwordIsValid == true {
        performSegue(withIdentifier: "loginToGames", sender: self)
    } else {

        self.incorrectLabel.isHidden = false
    }
}



 func validLogin() {

    let container = CKContainer.default()
    let pubDB = container.publicCloudDatabase

    //query users to find current user
    let query = CKQuery(recordType: "MyUsers", predicate: Predicate(format: "TRUEPREDICATE", argumentArray: nil))
    pubDB.perform(query, inZoneWith: nil, completionHandler: { (records, error) in

        if error == nil {

            for record in records! {

                if record.object(forKey: "Username") as? String == self.usernameField.text {

                    self.incorrectLabel.isHidden = true
                    self.usernameExists = true
                    print("searchUsername \(record.object(forKey: "Username") as? String)")
                } else {

                    self.incorrectLabel.isHidden = false
                    self.usernameExists = false
                    print("searchUsername error")
                }

            }

        } else {
            print("searchLoginError\(error)")
        }
    })

    let queryPassword = CKQuery(recordType: "MyUsers", predicate: Predicate(format: "TRUEPREDICATE", argumentArray: nil))
    pubDB.perform(queryPassword, inZoneWith: nil, completionHandler: { (records, error) in

        if error == nil {

            for record in records! {

                if record.object(forKey: "Password") as? String == self.passwordField.text {

                    self.incorrectLabel.isHidden = true
                    self.passwordIsValid = true
                    print("searchPassword \(record.object(forKey: "Password") as? String)")
                } else {

                    self.incorrectLabel.isHidden = false
                    self.passwordIsValid = false
                    print("searchPassword error")
                }

            }

        } else {
            print("searcherror\(error)")
        }
    })

}

func checkValidLogin() {

    let container = CKContainer.default()
    let pubDB = container.publicCloudDatabase

    //query users to find current user
    let query = CKQuery(recordType: "MyUsers", predicate: Predicate(format: "TRUEPREDICATE", argumentArray: nil))
    pubDB.perform(query, inZoneWith: nil, completionHandler: { (records, error) in

        //we do not need to check for error code 11 because a user should exist
        if error == nil {

            var userExists = false

            for record in records! {

                if record.object(forKey: "Username") as? String == self.usernameField.text {

                    if record.object(forKey: "Password") as? String == self.passwordField.text {

                        OperationQueue.main.addOperation {

                            userExists = true
                            UserDefaults.standard.set(self.usernameField.text!, forKey: "Username")
                            username = self.usernameField.text!


                        }

                    } else {

                        //user with the username exists, but the password does not match
                        self.incorrectLabel.isHidden = false

                    }

                }

            }

            if userExists == false {

                //user with that username does not exist
                self.incorrectLabel.isHidden = false

            }


        } else {

            print("searcherror \(error)")

        }

    })

}

Upvotes: 1

Views: 119

Answers (2)

CZ54
CZ54

Reputation: 5588

It's quite simple.

You are performing asynchronous call to check userExists and passwordIsValid but you are not wanting answer before doing your if test.

So the first time, the completionHandler is not finished, so userExists and passwordIsValid are set to false. On the second execution, the handler did set the value to true.

You should pass your if test as a completionHandler for the validLogin function

Sample :

func loginPressed() {

    validLogin() { (usernameExists, passwordIsValid) in 

        if usernameExists == true && passwordIsValid == true {
            performSegue(withIdentifier: "loginToGames", sender: self)
        } else {
            self.incorrectLabel.isHidden = false
        }
    }
}

func validLogin(completion : ((usernameExists : Bool, passwordIsValid : Bool) -> Void)) {

    let container = CKContainer.default()
    let pubDB = container.publicCloudDatabase
    let group = dispatch_group_create() //make sur both handler are triggered
    //query users to find current user

    dispatch_group_enter(group)
    let query = CKQuery(recordType: "MyUsers", predicate: Predicate(format: "TRUEPREDICATE", argumentArray: nil))
    pubDB.perform(query, inZoneWith: nil, completionHandler: { (records, error) in

        if error == nil {

            for record in records! {

                if record.object(forKey: "Username") as? String == self.usernameField.text {

                    self.incorrectLabel.isHidden = true
                    self.usernameExists = true
                    break
                } else {
                    self.incorrectLabel.isHidden = false
                    self.usernameExists = false
                }
            }

        } else {
            print("searchLoginError\(error)")
        }

        dispatch_group_leave(group)

    })

    dispatch_group_enter(group)
    let queryPassword = CKQuery(recordType: "MyUsers", predicate: Predicate(format: "TRUEPREDICATE", argumentArray: nil))
    pubDB.perform(queryPassword, inZoneWith: nil, completionHandler: { (records, error) in


        if error == nil {
            for record in records! {
                if record.object(forKey: "Password") as? String == self.passwordField.text {

                    self.incorrectLabel.isHidden = true
                    self.passwordIsValid = true
                    break
                } else {    
                    self.incorrectLabel.isHidden = false
                    self.passwordIsValid = false
                    print("searchPassword error")
                }

            }
        } else {
        print("searcherror\(error)")
        }
        dispatch_group_leave(group)

    })

    dispatch_group_notify(group, dispatch_get_main_queue()) {
    //You have both answers
        completion(self.usernameExists, passwordIsValid : self.passwordIsValid)

    })
}

Upvotes: 2

Ketan Parmar
Ketan Parmar

Reputation: 27428

Write below part in your completion handler,

    if usernameExists == true && passwordIsValid == true {
    performSegue(withIdentifier: "loginToGames", sender: self)
} else {

    self.incorrectLabel.isHidden = false
}

your above code is getting executing before usernameExists and passwordIsValid getting any value first time. so put this code snippet in final completion handler and your issue will be solved...!

Upvotes: 1

Related Questions