RufusV RufusV - 2 months ago 28
Swift Question

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)")

}

})

}

Answer

It's quiet 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