Adding Activity Indicator after Clicking "LOGIN"? - ios

I would like to add an Activity Indicator for my Login VC so that users will see that spinner thing once they click the "login" button. I have done multiple attempts and failed. Even if I put in codes for hiding the activity indicator, it just keeps animating even before clicking the "login" button. I deleted those codes, and have my original codes below (without activity indicator).
import UIKit
import Firebase
class LoginViewController: UIViewController {
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.image = #imageLiteral(resourceName: "background")
imageView.center = view.center
view.addSubview(imageView)
self.view.sendSubview(toBack: imageView)
}
//Outlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
//Login Action
#IBAction func loginAction(_ sender: AnyObject) {
if self.emailTextField.text == "" || self.passwordTextField.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
so I know the first step is probably dragging the activity indicator to the VC in Storyboard, but what's next?

You need to create a IBOutlet of dragged UIActivityIndicator. Then in viewDidLoadfunc hide this UIActivityIndicator with it's IBOutlet. When you click on Login Button, then unhide this activityIndicator and hide again, once receive response from login.

Create an IBOUtlet of your activity indicator from Storyboard to your Viewcontroller -
You can then in your ViewDidLoad or your storyboard set the below property
activityIndicator.hidesWhenStopped = true;
And when you want to start it, call
activityIndicator.startAnimating();
And to stop it from animating -
activityIndicator.stopAnimating();

The same way you created your IBOutlets of UITextField, create one with your UIActivityIndicator. Make sure your indicator's hidesWhenStopped is set to true in the storyboard.
Then animate it before calling your signin method, and stop it on the completion handler
#IBOutlet weak var activityIndicator: UIActivityIndicator!
//...
activityIndicator.startAnimating()
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in {
activityIndicator.stopAnimating()
//...
}

You can create UIActivityIndicatorView in your class programmatically & customize it in viewDidLoad
var activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
// Add below code in viewDidLoad
self.activityIndicator.hidesWhenStopped = true
self.activityIndicator.center = view.center
self.view.addSubView(self.activityIndicator)
Now do start & stop animating whereever you need
//Login Action
#IBAction func loginAction(_ sender: AnyObject) {
self.activityIndicator.startAnimating()
if self.emailTextField.text == "" || self.passwordTextField.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
self.activityIndicator.stopAnimating()
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}

In your storyboard, you can find checkbox.
startsAnimating
HidesWhenStops(check this in your storyboard.)
#IBOutlet weak var activityIndicator: UIActivityIndicator!
#IBAction func loginAction(_ sender: AnyObject) {
activityIndicator.startAnimating()
if self.emailTextField.text == "" || self.passwordTextField.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
activityIndicator.stopAnimating()
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
activityIndicator.stopAnimating()
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}

An alternative Approach. Adding the UIActivityViewController programatically:
In the LoginViewController class add
let myActivityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray)
In the viewDidLoad() add the following
myActivityIndicator.hidesWhenStopped = true
myActivityIndicator.center = view.center
view.addSubview(myActivityIndicator)
In #IBAction func loginAction(_ sender: AnyObject) in the else part
add
activityIndicator.startAnimating()
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in {
activityIndicator.stopAnimating()

I have written a class to use progress hud properly. You just need to drag and drop the class to your project...
https://github.com/emraz/ERProgressHud
For showing progress hud write ..
ERProgressHud.show()
For hiding progress hud write ..
ERProgressHud.hide()
In your code ..
//Login Action
#IBAction func loginAction(_ sender: AnyObject) {
if self.emailTextField.text == "" || self.passwordTextField.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
return
}
else {
ERProgressHud.show()
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
ERProgressHud.hide()
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}

Related

Swift 5 - Navigation Pages

I am just getting to work with Swift 5 and have to update my apps. I use....
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
self.present(vc, animated: true, completion: nil)
to push users from a sign-in screen to the main app, yet with the updates here's how it looks below (iPhone currently in dark-mode)...
Some questions. What is this functionality definitively called? and how do I go about manipulating it? Say I want to remove it because right now if the user is in the main app they can swipe down and go back to the sign-in screen which would definitely cause problems.
Sign-In View Controller Code
import UIKit
import Firebase
import RealmSwift
class StartViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Check if user is already logged-in so they don't have to sign-in again
checkUserSignIn()
// Setting textfield delegates so user can press enter and go to next textfield
self.email.delegate = self
self.password.delegate = self
let uid = Auth.auth().currentUser?.uid
print(uid)
print("printing the uid here")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Add a background view to the table view
let backgroundImage = UIImage(named: "startBackground")
let imageView = UIImageView(image: backgroundImage)
self.tableView.backgroundView = imageView
imageView.contentMode = .scaleAspectFill
}
// Check if user is already signed-in, if so push to main app
func checkUserSignIn() {
Auth.auth().addStateDidChangeListener({ (auth, user) in
if (user != nil) {
Database.database().reference().child("users").child((user?.uid)!).observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() {
print("user is logged in")
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
vc.modalPresentationStyle = .overCurrentContext
self.present(vc, animated: true, completion: nil)
}
})
}
})
}
#IBAction func login(_ sender: Any) {
if self.email.text == "" || self.password.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().signIn(withEmail: self.email.text!, password: self.password.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
// Proceed To App
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "home") {
} else {
print("Problem sending user into nature app")
}
}
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
#IBAction func createAccount(_ sender: Any) {
// Check user has entered text into fields
guard let email = email.text, email != "",
let password = password.text, password != ""
else {
// Throw alert message to user if fields are empty
let alert = UIAlertController(title: "Registration Error", message: "Please make sure you filled in all of the boxes to complete registration!", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
// Register a new user on Firebase
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
// Throw registration error / Account could already exist
if let error = error {
let alert = UIAlertController(title: "Registration Error", message: error.localizedDescription, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
return
}
guard let userID = user?.user.uid else {
return
}
// Database reference
let databaseRef = Database.database().reference()
// Set user information to firebase data structure
let userInfo = fireUsersData(email: email, profPicString: "", uid: userID)
databaseRef.child("users").child(userID).updateChildValues(userInfo.getUserDictionary(), withCompletionBlock: { (err, databaseRef) in
let UserToAdd = realmUserData()
UserToAdd.email = email
UserToAdd.uid = userID
//UserToAdd.saveDataToRealm()
if err != nil {
// Throw error is problem completeting
let alert = UIAlertController(title: "Error", message: (err?.localizedDescription)! as String, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
})
})
// Dismiss keyboard
self.view.endEditing(true)
// Proceed To App
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "home") {
} else {
print("Problem sending user into nature app")
}
}
}
// END OF FILE
}
Before presenting your ViewController give this option:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home")
vc.modalPresentationStyle = .overCurrentContext
self.present(vc, animated: true, completion: nil)
For ignoring dark mode style in didFinishLaunchingWithOptions write this:
if #available(iOS 13.0, *) {
window?.overrideUserInterfaceStyle = .light
}
UPDATE: Replace present to this code:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Home") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = vc

Attempt to present UIAlertController whose view is not in the window hierarchy - Swift Error

I'm trying to create an alert so when a user signs up and then wants to log back in they can be warned if the password is wrong because at the moment it just performs the segue and the attempt to alert fails. I'm using Firebase so the password that is entered into firebase on sign up should be the one users log in with.
import Foundation
import UIKit
import Firebase
class SignInViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var EmailAddressTextField: UITextField!
#IBOutlet weak var PasswordTextField: UITextField!
// Do any additional setup after loading the view.
override func viewDidLoad() {
super.viewDidLoad()
EmailAddressTextField.delegate = self
PasswordTextField.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
#IBAction func LogInButton(_ sender: Any) {
if (EmailAddressTextField.text != "" && PasswordTextField.text != ""){
Auth.auth().signIn(withEmail: EmailAddressTextField.text!, password: PasswordTextField.text!) { user, error in
if error == nil {
self.performSegue(withIdentifier: "LogInSegue", sender: nil)
} else {
let alert = UIAlertController(title: "Error", message: "Enter a correct email and password", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}
}
}
}
Just want to check something with you, as your description above is a little unclear. When you enter the wrong email/password combination, does your app still perform the "LogInSegue" (as well as failing to show the alert)?
If so, it sounds like you might have connected your segue to the UIButton instead of the UIViewController.
To check this, click on your segue in the Storyboard and see if the UIButton is highlighted.
If it is, then delete this segue and follow the instruction below to connect your new segue from the view controller:
You are presenting UIAlertController on SignInViewController so at that time SignInViewController is not in navigation stack.
So when you are presenting UIAlertController at that time check the self.navigationController?.viewControllers and verify that it is in stack or not.
for eg.
//check before self.presnt...
print(self.navigationController?.viewControllers)
So you need to make sure that when you are presenting a view controller over another view controller that must be in navigation stack otherwise you will get this message in log.
Attempt to present UIAlertController whose view is not in the window hierarchy
Use the following function to show alert over root view controller
func showAlert(title: String, msg: String, actions:[UIAlertAction]?) {
var actions = actions
let alertVC = UIAlertController(title: title, message: msg, preferredStyle: .alert)
if actions == nil {
actions = [UIAlertAction(title: "OK", style: .default, handler: nil)]
}
for action in actions! {
alertVC.addAction(action)
}
if let rootVC = UIApplication.shared.delegate?.window??.rootViewController {
rootVC.present(alertVC, animated: true, completion: nil)
} else {
print("Root view controller is not set.")
}
}
Usage
self.showAlert(title: "My App", msg: "your message", actions: nil)
You need to use this with your code like this...
class SignInViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var EmailAddressTextField: UITextField!
#IBOutlet weak var PasswordTextField: UITextField!
// Do any additional setup after loading the view.
override func viewDidLoad() {
super.viewDidLoad()
EmailAddressTextField.delegate = self
PasswordTextField.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
#IBAction func LogInButton(_ sender: Any) {
if (EmailAddressTextField.text != "" && PasswordTextField.text != ""){
Auth.auth().signIn(withEmail: EmailAddressTextField.text!, password: PasswordTextField.text!) { user, error in
if error == nil {
self.performSegue(withIdentifier: "LogInSegue", sender: nil)
} else {
// let alert = UIAlertController(title: "Error", message: "Enter a correct email and password", preferredStyle: .alert)
// let action = UIAlertAction(title: "OK", style: .default, handler: nil)
// alert.addAction(action)
// self.present(alert, animated: true, completion: nil)
//use like this...
self.showAlert(title: "Error", msg: "Enter a correct email and password", actions: nil)
}
}
}
}
//###############################################
func showAlert(title: String, msg: String, actions:[UIAlertAction]?) {
var actions = actions
let alertVC = UIAlertController(title: title, message: msg, preferredStyle: .alert)
if actions == nil {
actions = [UIAlertAction(title: "OK", style: .default, handler: nil)]
}
for action in actions! {
alertVC.addAction(action)
}
if let rootVC = UIApplication.shared.delegate?.window??.rootViewController {
rootVC.present(alertVC, animated: true, completion: nil)
} else {
print("Root view controller is not set.")
}
}
//###############################################
}
Present it in main activity :
dispatch_async(dispatch_get_main_queue(), ^{
let alert = UIAlertController(title: "Error", message: "Enter a correct email and password", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
});

Attempt to present UIAlertController whose view is not in the window hierarchy

more specifically the error warning I ma getting is:
Attempt to present UIAlertController whose view is not in the window hierarchy!
I am currently creating a signup page that ask user to fill few specific details such as Name, Country, Email, Password and etc. To make sure user provide all the relevant information I am trying to write a code to send an alert if user does not provide all the information. I have wrote the code taking help from stakeoverflow.
Problem: Whenever user left any field blank it is not showing the alert and by default performing a segue that takes user to signin page. This is the first time I am creating an alert and hence don't what is going wrong (I believe 95% of my code is in place)
can anyone help?
#IBAction func signUpPressed(_ 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 above error in the Xcode console but the below code is not working
//setting error message if not all fiels filled
let alertController = UIAlertController(title: "Error", message: "Please fill all fields", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
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)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.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!,])
}
}
}
Action may be out of main thread
DispatchQueue.main.async {
///print errror message
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
Try this approach
check for white space like that
let nameTrimmed = self.nameText.text?.trimmingCharacters(in: .whitespacesAndNewlines)
let genderTrimmed = self.genderText.text?.trimmingCharacters(in: .whitespacesAndNewlines)
let countryTrimmed = self.countryText.text?.trimmingCharacters(in: .whitespacesAndNewlines)
let schoolTrimmed = self.schoolText.text?.trimmingCharacters(in: .whitespacesAndNewlines)
if nameTrimmed.text == "" || genderTrimmed.text == "" || countryTrimmed.text == "" || schoolTrimmed.text == ""
#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
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!,])
}
}
}
}

Xcode 8.3.3: How to Remember Username and Password and Add Touch-ID Authentication

My current project has a login page, but I find that the user must enter their username and password again when they log in. How do I make it easier for them, by implementing "remember username and password" functionality and adding Touch ID?
My code is as follows:
import UIKit
import Firebase
class LoginViewController: UIViewController {
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.image = #imageLiteral(resourceName: "background")
imageView.center = view.center
view.addSubview(imageView)
self.view.sendSubview(toBack: imageView)
}
//Outlets
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
//Login Action
#IBAction func loginAction(_ sender: AnyObject) {
if self.emailTextField.text == "" || self.passwordTextField.text == "" {
//Alert to tell the user that there was an error because they didn't fill anything in the textfields because they didn't fill anything in
let alertController = UIAlertController(title: "Error", message: "Please enter an email and password.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
you have a couple of ways to save your user Credentials. Most common way is to save those in Keychain.
KeyChain Swift
After that you can user your touchID authentication, by calling the default methods to implement this. Here is a nice tutorial how you should do it:
Touch ID for Local Authentication

ViewController dismiss swift ios

Hello my english is not very good, I apologize in advance.
I have a problem with my application. The scenario is as follows I have my rootViewController assigned to my ViewController controller which is my start. I have other screens that are a description screen where I have two login and registration buttons which when preloaded bring me to their controller.
Now, when I am on the log full screen form and I send the dismiss order:
ViewController registration
self.dismiss(animated: false, completion: nil)
And all ok the view is hidden but when entering the previous screen that was the description I have a validation if there is already a user if there is the dismiss order:
ViewController Description App
self.dismiss(animated: false, completion: nil)
But it does not perform the action.
Code
UIViewController
class ViewController: UIViewController {
override func viewDidLoad() {
FIRAuth.auth()!.addStateDidChangeListener() { auth, user in
if user == nil {
let descriptionController = DescriptionController()
present(descriptionController, animated: true, completion: nil)
}
}
}
}
DescriptionController
class DescriptionController: UIViewController {
#IBOutlet weak var sign_in_custom: UIButton!
override func viewDidLoad() {
FIRAuth.auth()!.addStateDidChangeListener() { auth, user in
if user != nil {
self.dismiss(animated: false, completion: nil)
}
}
sign_in_custom.addTarget(self, action: #selector(changeToSingIn), for: [.touchUpInside])
}
func changeToSingIn() {
let singInController = SingInController()
present(singInController, animated: true, completion: nil)
}
}
SingInController
class SingInController: UIViewController {
#IBOutlet weak var sign_in_custom: UIButton!
override func viewDidLoad() {
sign_in_custom.addTarget(self, action: #selector(singIn), for: [.touchUpInside])
}
func showLoad() {
let alert = UIAlertController(title: nil, message: "Please wait...", preferredStyle: .alert)
alert.view.tintColor = UIColor.black
let loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(10, 5, 50, 50) ) as UIActivityIndicatorView
loadingIndicator.hidesWhenStopped = true
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
loadingIndicator.startAnimating();
alert.view.addSubview(loadingIndicator)
present(alert, animated: true, completion: nil)
}
func hideLoad() {
self.dismiss(animated: false, completion: nil)
}
func singIn() {
if (emailVarification()){
if (passwordVarification()){
showLoad()
guard let email = emailTextField.text else { return }
guard let password = passwordTextField.text else { return }
FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in
hideLoad()
if (user != nil) {
self.dismiss(animated: false, completion: nil)
} else {
let alert = UIAlertController(title: "Error", message: "This is a error", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
} else {
let alert = UIAlertController(title: "Error", message: "This is a error", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
} else {
let alert = UIAlertController(title: "Error", message: "This is a error", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
sequence
This is because the second controller has basically just been placed on the top of the existing one. The first view is still running under the second view, and when the second view is dismissed the first view won't call ViewDidLoad. So to solve it, you probably want to add it inside the ViewDidAppear Function.
Use this code in ViewdidAppear:
FIRAuth.auth()!.addStateDidChangeListener() { auth, user in
if user != nil {
self.dismiss(animated: false, completion: nil)
}
}
sign_in_custom.addTarget(self, action: #selector(changeToSingIn), for: [.touchUpInside])
Instead of having the DescriptionController dismiss itself, a better way would be for it would be to instead inform the ViewController that the user has signed in and also returns any errors, if necessary. Then the ViewController can perform any additional steps needed based on successful or failed sign-in. This could be accomplished by using the delegate pattern (DescriptionController defines a protocol and ViewController implements it).

Resources