I have the following code:
#IBAction func loginTapped(_ sender: Any) {
let error = validateFieldsSignIn()
if error != nil {
showErrorSignIn(error!)
} else {
guard let emailsignin = emailSignIn?.text!.trimmingCharacters(in: .whitespacesAndNewlines),
let passwordsignin = passwordSignIn?.text!.trimmingCharacters(in: .whitespacesAndNewlines) else {
return showErrorSignIn("Fill in all fields")
}
Auth.auth().signIn(withEmail: emailsignin, password: passwordsignin) { (user, error) in
if error != nil {
print("There was an error")
self.errorLabel3.text = "Invalid username or password"
self.errorLabel3.alpha = 1
} else {
self.transitionToHome()
}
}
}
}
Although unless the fields aren't filled in the else statement gets triggered and the error label says fill in all fields, essential the code that is getting triggered is this:
else {
return showErrorSignIn("Fill in all fields")
}
I tried putting the Auth.auth().signIn() inside the else block although I got the following error:
Variable declared in 'guard' condition is not usable in its body
How do I fix this error message?
Related
I am trying to query my Firestore database to see if a desired username is taken. The query works, however I need to return a value if it is empty or not to see if the username already exists. I am trying to use a completion handler but it doesn't seem to work:
func checkUserTaken(cleanUsername: String ,completion:#escaping(String) -> (Void)){
let db = Firestore.firestore()
var userTaken: String = ""
let docRef = db.collection("users").whereField("username", isEqualTo: cleanUsername)
docRef.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
if(querySnapshot!.documents.isEmpty){
print("user is available")
userTaken = "user is available"
}
else{
print("user is taken")
userTaken = "user is taken"
}
}
completion(userTaken)
}
This task is a good way to learn some important and helpful things about Swift, such as naming conventions, deciding what to return from functions (you chose a string, I opted for a boolean), accounting for errors, etc.
func checkUsername(_ username: String, completion: #escaping (_ taken: Bool?) -> Void) {
Firestore.firestore().collection("users").whereField("username", isEqualTo: username).getDocuments() { (snapshot, err) in
if let snapshot = snapshot {
if snapshot.documents.isEmpty {
completion(false)
} else {
completion(true)
}
} else {
if let err = err {
print(err)
}
completion(nil)
}
}
}
Usage
checkUsername("drake") { (taken) in
guard let taken = taken else {
// handle error, maybe retry?
return
}
if taken {
// prompt user username is taken
} else {
// username not taken, proceed
}
}
In the signature of the function, I labeled the boolean in the completion closure (taken), which the Swift compiler does not require you do but I think can be very helpful.
By the way, this function can return anything, even a Result object which is a neat way to return an object or an Error in a single object. But I think returning a boolean is straightforward enough here. I made the boolean an optional so the function can return three possible states (true, false, or nil) to give you a way to handle errors.
String return
func checkUsername(_ username: String, completion: #escaping (_ name: String?) -> Void) {
Firestore.firestore().collection("users").whereField("username", isEqualTo: username).getDocuments() { (snapshot, err) in
if let snapshot = snapshot {
if snapshot.documents.isEmpty {
completion(username) // return the username if it's available
} else {
completion("") // return an empty string if taken
}
} else {
if let err = err {
print(err)
}
completion(nil) // return nil if error
}
}
}
checkUsername("drake") { (name) in
guard let name = name else {
// handle error
return
}
if name.isEmpty {
// username taken
} else {
print(name) // username not taken
}
}
After unsuccessful attempt of FaceId for two times, pop up window does not auto close. Is there any handler to auto close the FaceId after all unsuccessful attempts or any handler to control the FaceId pop up.
The behaviour of pop up is different than touchId.
Please help.
Code is below:-
func authentication() {
let localAuthenticationContext = LAContext()
localAuthenticationContext.localizedFallbackTitle = “Failed Authentication”
var authError: NSError?
if localAuthenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
localAuthenticationContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString) { success, error in
if success {
print("Authentication Successful”);
} else {
print("Authentication failure");
guard let error = error else {
return
}
let errorMessage = self.errorMessageForFails(errorCode: error._code)
print(errorMessage);
}
}
} else {
guard let error = authError else {
return
}
let errorMessage = self.errorMessageForFails(errorCode: error._code)
display(errorMessage)
}
}
#IBAction func signup(_ sender: Any) {
print("began signup process")
guard let fullname = fullnameField.text, fullname != "" else {
print("FULLNAME field is empty")
return
}
guard let username = usernameField.text, username != "" else {
print("USERNAME field is empty")
return
}
guard let email = emailField.text, email != "" else {
print("EMAIL field is empty")
return
}
guard let password = passwordField.text, password != "" else {
print("PASSWORD field is empty")
return
}
print("all fields good")
mainActivityIndicator.startAnimating()
self.checkUsernameAvailability(username: username, completion: {
result in
print("starting check")
...
})
print("finished the function")
}
The issue is basically that nothing inside of the checkUsernameAvailability function will call.
The console looks like this:
began signup process
all fields good
finished the function
it does not print 'starting check' or run any code at all inside of the function.
This is probably a rookie error and I am sorry if it is a stupid question.
Future thanks.
P.S I checked the entire console and there is no error relating to this.
EDIT: Here is the code inside the function
func checkUsernameAvailability(username: String, completion: #escaping (Bool) -> Void) {
_ = Database.database().reference().child("usernames").observe(.childAdded, with: {
snapshot in
print("checking username availability")
print(snapshot)
completion(true)
let dict = snapshot.value as? [String: AnyObject]
for handled in (dict?.values)! {
print("stumbled")
print(handled)
if username.lowercased() == handled.lowercased {
completion(false)
}
}
})
}
And...
self.checkUsernameAvailability(username: username, completion: {
result in
print("starting check")
if result == false {
print("username is taken")
self.mainActivityIndicator.stopAnimating()
return
} else {
Auth.auth().createUser(withEmail: email, password: password, completion: {
(user, error) in
if error != nil {
print(error ?? "ERROR OCCURED")
self.mainActivityIndicator.stopAnimating()
return
}
let ref = Database.database().reference()
ref.child("~/users/\(user?.uid ?? "0")/username").setValue(username.lowercased())
ref.child("~/users/\(user?.uid ?? "0")/fullname").setValue(fullname)
ref.child("usernames/\(user?.uid ?? "0")").setValue(username.lowercased())
self.mainActivityIndicator.stopAnimating()
})
}
})
The Database.database().reference().child("usernames").observe call simply never calls the with block. I would assume that block is called when the event .childAdded is observed, but I see no code that would add a child. To me this looks like you are setting up an asynchronous observer, so this code will not run when you make the call, it will run when the monitored event takes place.
I have been trying to change the content in an array called testArray in the class Collabs and then save it back to the parse server.
#IBAction func addToArray(_ sender: AnyObject) {
var objectToSave: PFObject?
let query = PFQuery(className: "Collabs")
query.getObjectInBackground(withId: collabID) { (object, error) in
if error != nil {
print(error)
} else if let content = object {
objectToSave = content
}
if objectToSave != nil {
objectToSave!["testArray"] = ["foo","bar","foobar"]
objectToSave!.saveInBackground(block: { (success, error) in
if error != nil {
print("ERROR")
} else {
print("SUCCESS")
}
})
}
}
I've seen quite a few posts that talk about access rights however, to the best of my knowledge, the class Collabs has public read and write enabled
sorry I didnt check it that deeply before, try this
var objectToSave: PFObject?
let query = PFQuery(className: "Collabs")
query.getObjectInBackground(withId: collabID) { (object, error) in
if error != nil {
print(error)
} else {
if let content = object {
objectToSave = content
}
if objectToSave != nil {
objectToSave!["testArray"] = ["foo","bar","foobar"]
objectToSave!.saveInBackground(block: { (success, error) in
if error != nil {
print("ERROR")
} else {
print("SUCCESS")
}
})
}
}
}
So I've been attempting to update my code to Swift 2.0 syntax, but I can't seem to get my Parse login to work. I looked over the documentation changes and added the result block for my login, but I'm getting the error "'(, ) throws -> Void' is not convertible to 'PFUserResultBlock?'"
Here is the line of code:
PFUser.logInWithUsernameInBackground(usernameTextField.text!, password: passwordTextField.text!, block: { (user,error) -> Void in
if user != nil {
This Code might solve your problem.
PFUser.logInWithUsername(inBackground: emailTextField.text!, password: passwordTextField.text!, block: { (user, error) in
self.activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil {
var displayErrorMessage = "Please try again later"
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Login Error", message: displayErrorMessage)
} else {
print("logged inn")
self.performSegue(withIdentifier: "showUserTable", sender: self)
}
})
Try this version
PFUser.logInWithUsernameInBackground(usernameTextField.text!, password: passwordTextField.text!) { (user:PFUser?, error:NSError?) -> Void in
if user != nil {
print("Login Successful")
} else {
print("Login Failed")
}
}