AlertController - conflict with UIViewController - ios

I'm working on an iOS project using Swift. I have simple login/register/lost password view controllers for security using Firebase. The issue is with the Reset Password View Controller. If a user clicks on it, they are sent (presented modally) to lost password view controller.
The problem with the current code is that when Firebase finds the entered email and sends a password reset email, I present Alert controller for confirmation for the user. The issue is that when I click "ok" on the Alert Controller, I want the Reset Password View Controller to be dismissed as well. Not sure why it's not working now. I do get emails, but when I click the OK button on the Alert controller, it only dismisses the Alert controller and the self.dismissViewControllerAnimated(true, completion: nil) doesn't seem to dismiss the modally presented Reset Password View Controller.
I tried with self.dismissViewController(true, completion: nil) as well as self.performSegueWithIdentifier("goToLoginVC", sender: nil). Non seems to work and I can't figure why.
Here's the function itself:
#IBAction func resetPasswordPressed(sender: AnyObject) {
let email = emailTextField.text
if email != "" {
DataService.ds.REF_BASE.resetPasswordForUser(email, withCompletionBlock: { error in
if error != nil {
// Error - Unidentified Email
showAlert(title: "Unidentified Email Address", msg: "Please, re-enter the email you have registered with.", actionButton: "OK", viewController: self)
} else {
// Success - Sent recovery email
let alertController = UIAlertController(title: "Email Sent", message: "An email has been sent. Please, check your email now.", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)
self.dismissViewControllerAnimated(true, completion: nil)
}
})
} else {
showAlert(title: "Error!", msg: "Email is required in order to reset your password. Please, enter your email. ", actionButton: "OK", viewController: self)
}
}

Do it this way:
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle. Default, handler: { action in
//Add your logic here
}))

Someone answered and provided the solution but removed his answer after it. So, this is what he said and it worked well (so credit goes to that person!):
#IBAction func resetPasswordPressed(sender: AnyObject) {
let email = emailTextField.text
if email != "" {
DataService.ds.REF_BASE.resetPasswordForUser(email, withCompletionBlock: { error in
if error != nil {
// Error - Unidentified Email
showAlert(title: "Unidentified Email Address", msg: "Please, re-enter the email you have registered with.", actionButton: "OK", viewController: self)
} else {
// Success - Sent recovery email
let alertController = UIAlertController(title: "Email Sent", message: "An email has been sent. Please, check your email now.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: { action in
self.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alertController, animated: true, completion: nil)
}
})
} else {
showAlert(title: "Error!", msg: "Email is required in order to reset your password. Please, enter your email. ", actionButton: "OK", viewController: self)
}
}

Related

receiving error message "the email address is already in use by another account" when attempting to register with new email

I have a register page with 3 UITextFields and a register button. When the button is clicked, the account is supposed to be registered to my Firebase Database. However, whenever I click the button, the SVProgressHUD.showSuccess() appears, but so does an UIAlert saying "the email address is already in use by another account" in addition to the preformSegue not occurring. This error cannot be true though because none of the emails I am using are registered to my app.
Below is the code I currently am using:
func register() {
Auth.auth().createUser(withEmail: registerEmail.text!, password: registerPassword.text!) { (user, error) in
if error == nil {
SVProgressHUD.dismiss()
SVProgressHUD.showSuccess(withStatus: "Welcome \(self.registerEmail.text!)")
self.performSegue(withIdentifier: "goToTheHome", sender: self)
}
else {
SVProgressHUD.dismiss()
print(error as Any)
print("")
let alert = UIAlertController(title: "Error", message: error!.localizedDescription, preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(okAction)
self.present(alert,animated: true) }
}
}
#IBAction func createAccount(_ sender: UIButton) {
SVProgressHUD.show()
if registerPassword.text == confirmPassword.text {
register()
}
else {
SVProgressHUD.dismiss()
let alert = UIAlertController(title: "Error", message: "Passwords do not match", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(okAction)
self.present(alert,animated: true)
}
}
If the new account was successfully created, the user is signed in, and you can get the user's account data from the result object that's passed to the callback method.
You can try to check your user (result) object in the console..

Trouble implementing UIAlertController. Cant get alert to show up

I have set an alert to be shown as any error occurs when some user tries to request a new password through firebase, but it is not working.
The print("problems with email field") is being printed so I believe I have made something wrong when writing the alert part.
#IBAction func recuperarSenha(_ sender: Any) {
Auth.auth().sendPasswordReset(withEmail: self.loginTextView.text!) { error in
if error != nil {
print("problems with email field")
let alert = UIAlertController(title: "Couldn't send recover message", message: "Check if e-mail field is properly filled.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK!", style: .default, handler: nil))
}
}
}
You need to present your alert after creating it. Add the following code after adding action:
self.present(alert, animated: true, completion: nil)
Edited version of your code:
#IBAction func recuperarSenha(_ sender: Any) {
Auth.auth().sendPasswordReset(withEmail: self.loginTextView.text!) { error in
if error != nil {
print("problems with email field")
let alert = UIAlertController(title: "Couldn't send recover message", message: "Check if e-mail field is properly filled.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK!", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}

Firebase Reset Password IOS App xcode

I'm currently developing an app that has a login page with a login button and main menu button. I've created everything and is working pretty well for the time being. I'm using Firebase as my backend database.
I wanted to create a 'forgot password' button which i already did and seems like its working but the only problem is it doesn't give me an alert when it sends the email, it just sends it, but i get the alert when i enter an email which is not in the user authentication. Below is my code for the forget password button:
#IBAction func frgtpassTapped(_ sender: Any) {
Auth.auth().sendPasswordReset(withEmail: emailTextField.text!) { error in
if self.emailTextField.text?.isEmpty==true{
let resetFailedAlert = UIAlertController(title: "Reset Failed", message: "Error: \(String(describing: error?.localizedDescription))", preferredStyle: .alert)
resetFailedAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetFailedAlert, animated: true, completion: nil)
}
if error != nil && self.emailTextField.text?.isEmpty==false{
let resetEmailAlertSent = UIAlertController(title: "Reset Email Sent", message: "Reset email has been sent to your login email, please follow the instructions in the mail to reset your password", preferredStyle: .alert)
resetEmailAlertSent.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetEmailAlertSent, animated: true, completion: nil)
}
}
}
I accept if anyone downvotes this post but please if you do, comment below the reason. Any help would be much appreciated!
Please this code
Auth.auth().sendPasswordReset(withEmail: emailTextField.text!) { error in
DispatchQueue.main.async {
if self.emailTextField.text?.isEmpty==true || error != nil {
let resetFailedAlert = UIAlertController(title: "Reset Failed", message: "Error: \(String(describing: error?.localizedDescription))", preferredStyle: .alert)
resetFailedAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetFailedAlert, animated: true, completion: nil)
}
if error == nil && self.emailTextField.text?.isEmpty==false{
let resetEmailAlertSent = UIAlertController(title: "Reset Email Sent", message: "Reset email has been sent to your login email, please follow the instructions in the mail to reset your password", preferredStyle: .alert)
resetEmailAlertSent.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(resetEmailAlertSent, animated: true, completion: nil)
}
}
}
It is clear from your code, that you are passing the unWrapped value to the closure, so the textField must contains some value in it.
THIS LINE IN YOUR CODE: if self.emailTextField.text?.isEmpty==true {
will never be entered inside condition.
It should be updated to like:
#IBAction func frgtpassTapped(_ sender: Any) {
//BEFORE SENDING DATA FOR AUTHENTICATION, CHECK FOR THE isEmpty CONDITIONS HERE
Auth.auth().sendPasswordReset(withEmail: emailTextField.text!) { error in
DispatchQueue.main.async {
if error != nil {
// YOUR ERROR CODE
} else {
//YOUR SUCCESS MESSAGE
}
}
}
}

segue performed before the UIAlertController in swift

I have just coded a signup page in which if user does not enter text in any of the uitextfield then it should receive an error message (UIAlert) ; else (if user enter text in all uitextfield) signup page will present for Firebase Authentication.
in my code, user will direct to sign-in page only if authentication successfully complete else it should remain in signup page with alert message.
Problem - my code is able to produce alert message but same time it is taking user to sign-in page automatically even when there is an error. which means it is performing a segue that takes user to sign-in page i.e. segue unwinding irrespective of alert message.
can anyone help me why this may be happening?
#IBAction func registerPressed(_ sender: Any) {
if nameText.text!.isEmpty || genderText.text!.isEmpty || countryText.text!.isEmpty || yourSchool.text!.isEmpty || yourClass.text!.isEmpty {
print("Please fill all fields") //my code is printing this error
//alert message popup - my code is ble to produce this alert but same it is performing segue and taking user to signin page
//ideally, i want user to be in signup page unless all criteria meet
let alertController = UIAlertController(title: "Error", message: "Please fill all fields", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action:UIAlertAction) in
print("Okay")
}))
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindowLevelAlert
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(alertController, animated: true, completion: nil)
}
else {
Auth.auth().createUser(withEmail: yourEmail.text!, password: yourPassword.text!) { (user, error) in
if error != nil {
///print errror message
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action:UIAlertAction) in
print("Okay")
}))
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindowLevelAlert + 1;
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(alertController, animated: true, completion: nil)
}
else {
print("You have successfully signed up")
self.performSegue(withIdentifier: "JoinUs2SignPage", sender: self)
//updating user information
let userID = Auth.auth().currentUser!.uid
let usertype: String = "Student"
self.ref.child("users").child(userID).setValue(["usertype": usertype ,"username": self.nameText.text!, "usergender": self.genderText.text!, "usercountry": self.countryText.text!, "userschool": self.yourSchool.text!, "userclass": self.yourClass.text!,])
}
}
}
}
From this bit of code it doesn't really look like anything is wrong. However, you should block the UI while Auth.auth().createUser(...) is running. Otherwise there's a chance that you call registerPressed with everything correct, but then delete the text from a label and call it again before the callback. That way you have an alert and then the segue is called.
You're also doing something quite crazy with the way that you're presenting your alerts. Instead of creating a new window, adding to it a view controller and all that jazz, just call self.present(alertController, animated: true). E.g.
let alertController = UIAlertController(title: "Error", message: "Please fill all fields", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action:UIAlertAction) in
print("Okay")
}))
self.present(alertController, animated: true)
Remove the segue and push to destination view controller programmatically.
self.navigationController?.pushViewController(destinationVC, animated: true)
I was doing a silly mistake where I created the segue directly on IBAction and hence whenever I was pressing the button it was performing the segue irrespective UIAlerts. my updated code is below :
#IBAction func registerPressed(_ sender: Any) {
if nameText.text!.isEmpty || genderText.text!.isEmpty || countryText.text!.isEmpty || yourSchool.text!.isEmpty || yourClass.text!.isEmpty {
//alert message popup
let alertController = UIAlertController(title: "Error", message: "Please fill all fields", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action:UIAlertAction) in
print("Okay")
}))
self.present(alertController, animated: true, completion: nil)
}
else {
Auth.auth().createUser(withEmail: yourEmail.text!, password: yourPassword.text!) { (user, error) in
if error != nil {
///print errror message
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action:UIAlertAction) in
print("Okay")
}))
self.present(alertController, animated: true, completion: nil)
}
else {
let alertController = UIAlertController(title: "Congratulation", message: "You have successfully signed up", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Get Started", style: .default, handler: { (action:UIAlertAction) in
self.performSegue(withIdentifier: "back2SignPage", sender: self)
}))
self.present(alertController, animated: true, completion: nil)
//updating user information
let userID = Auth.auth().currentUser!.uid
let usertype: String = "Student"
self.ref.child("users").child(userID).setValue(["usertype": usertype ,"username": self.nameText.text!, "usergender": self.genderText.text!, "usercountry": self.countryText.text!, "userschool": self.yourSchool.text!, "userclass": self.yourClass.text!,])
}
}
}
}

Firebase login system

So here is the deal. Right now I have a viewcontroller where the user can signup, and it is working (checked in Firebase console). The next step is that I have another view with two fields and a Log in button. That login button now has a segue to the third view, home. But it is possible to click it even though nothing has been entered in the two textfields. The button should only work if the user enters his or he details he made in the signup view, thus logging in.
How can I do this?
already have the login code:
#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)
}
In the second if statement you see that it clears the fields to show the login worked.
What i need is that users can only login if the correct details are filled in, that are in the Firebase database.
Instead of checking if there isnt any errors, check that there is data is the user object like this.
FIRAuth.auth()?.signInWithEmail(self.emailField.text!, password: self.passwordField.text!) { (user, error) in
if user != nil
{
let VC = storyboard?.instantiateViewControllerWithIdentifier("Identifier") as! AccountViewController //The file that controls the view
self.presentViewController(VC, animated: true, completion: nil)
}
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)
}
I managed to fix it by adding self. infront of
storyboard?.instantiate.
Thus creating:
self.storyboard?instantiate.

Resources