How do i keep a user login in app ? swift 5

1.9k Views Asked by At

Hello i have made app which include login and signup functionality which works fine but i am not able to keep user sign in when i close the app; it returns the user to the main view controller where a user will have to choose between sign up or log in.

Can anyone help ?

Here is my code: AppDelegate, Login, SignUp

AppDelegate:

import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        sleep(2);
        FirebaseApp.configure()
        return true
    }
}

Login:

import UIKit
import Firebase
    
class LoginController: UIViewController {
    
    // MARK: - Properties
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var login: UIButton!
    @IBOutlet weak var emailTextField: UILabel!
    
    var email = String()
    
    // MARK: - Init
    override func viewDidLoad() {
        super.viewDidLoad()
        emailTextField.text = email
    }
    
    // MARK: - Selectors
    
    @IBAction func loginButton(_ sender: UIButton) {
        
        guard let password = passwordTextField.text else {return}
        
        let finalPassword = password.trimmingCharacters(in: .whitespacesAndNewlines)
            
        //Password Validation and Alert
        if Utilities.isPasswordValid(finalPassword) == true {
            print("Password is Valid")
        } else {
            print("Password is not Valid")
            let myAlert = UIAlertController(title:"",message:"Please make sure your password is at least six characters, includes at least one number or special character, and is not a commonly used password.",preferredStyle:UIAlertController.Style.actionSheet)
            let okAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.destructive, handler: nil)
            myAlert.addAction(okAction)
            self.present(myAlert, animated: true, completion: nil)
        
            return
        }
        
        loginUserIn(withEmail: email, password: password)
     }
    
    // MARK: - API
    
    func loginUserIn(withEmail email:String, password: String) {
        
        Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
        
        if let error = error {
            print("Failed to sign in", error.localizedDescription)
            return
        }
        print("Success Log In")
        
            UserDefaults.standard.set(true, forKey: "nil")
            UserDefaults.standard.synchronize()
    }
  }
}

SignUp:

import UIKit
import Firebase

class SignUpController: UIViewController {
    
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var signUp: UIButton!
    @IBOutlet weak var emailText: UILabel!
    
    var email = String()
    
    // MARK: - Init
    
    override func viewDidLoad() {
        super.viewDidLoad()
        emailText.text = email
        signUp.addTarget(self, action: #selector(signUpButton), for: .touchUpInside)
    }

    // MARK: - Selectors
    
    @IBAction func signUpButton(_ sender: Any) {
    
    guard let password = passwordTextField.text,
                // use Swift's ability to infer the type here (and a couple other places)
                case let finalPassword = password.trimmingCharacters(in: .whitespacesAndNewlines),
                Utilities.isPasswordValid(finalPassword) else {
                // If we get here then either the password is null
                // or the password is not valid
                print("Password is not valid")

                // we need to display the alert, I'll move that into another function
                showPasswordInvalidAlert()

                return
            }

            // If we get here the password is valid
            print("Password is valid:", finalPassword)

        
        createUser(withEmail: email, password: password)
    }
        
    func showPasswordInvalidAlert() {
        // this is an alert not an action sheet
        let alert = UIAlertController(title: "", message: "Please make sure your password is at least six characters, includes at least one number or special character, and is not a commonly used password.", preferredStyle: .actionSheet)
        // this is not a destructive action
        let okAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
        alert.addAction(okAction)
        self.present(alert, animated: true, completion: nil)
    }
   
    // MARK: - API
    
    func createUser(withEmail email:String, password: String) {
        
        Auth.auth().createUser(withEmail: email, password: password) { (result, error) in
            
            if let error = error {
                print("Failed to sign up", error.localizedDescription)
                return
            }
            
            guard let uid = result?.user.uid else {return}
            
            let values = ["email": email]
            
            Database.database().reference().child("users").child(uid).updateChildValues(values, withCompletionBlock: { (error, ref) in
                
                if let error = error {
                    print("Falied to update", error.localizedDescription)
                    return
                }
                let mainStoryBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
                
                guard let controller = mainStoryBoard.instantiateViewController(withIdentifier: "SubsViewController") as? SubsViewController else {
                    print("Error")
                    return
                }
                
                self.navigationController?.pushViewController(controller, animated: true)
                
               // self.present(controller, animated: true, completion: nil)
            
            })
        }
    }
}
2

There are 2 best solutions below

2
On
  • set a boolean check.

  • set it to true on logIn.

  • set it as false on logout.

  • check its status on sceneDelegate

  • load the viewcontroller according to the value present.

    let isLoggedIn = userdefaults.standard.bool(forKey: "loggedInValue")

    if isLoggedIn == true{ 
     print("loggedIn")
    }else{
     print("loggedOut")
    }
    

in your sceneDelegate set

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    let window = UIWindow(windowScene: scene as! UIWindowScene)
    // Assign window to SceneDelegate window property
    self.window = window
    
    if let loggedIn = UserDefaults.standard.bool(forKey: "IsUserLoggedIn") as? Bool{
        if loggedIn{
            let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoggedInScreen")

            self.window?.rootViewController = initialViewController
        }else{
            let initialViewController = storyboard.instantiateViewController(withIdentifier: "SignUpScreen")
            self.window?.rootViewController = initialViewController
        }
    }else{
        let initialViewController = storyboard.instantiateViewController(withIdentifier: "SignUpScreen")
        self.window?.rootViewController = initialViewController
    }
    self.window?.makeKeyAndVisible()
    guard let _ = (scene as? UIWindowScene) else { return }
}
1
On

follow the steps:-

  • once user successfully login set UserDefaults.standard.set(true, forKey: "islogin")
  • add the below code into appdelegate
private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
           
           let islogin = UserDefaults.standard.object(forKey: "token")
           if islogin {
               //set your login viewcontroller as root viewcontroller
           }else{
               //open the home screen 
           }
           return true
       }
  • don't forget to set userdefault false on time of logout.