Search code examples
iosswiftuiviewcontrollernsuserdefaultsuserdefaults

Accessing UserDefaults in Swift from other viewControllers


In my application, I use UserDefaults to store the user's login status (whether they are logged in or not), and their username. It works fine in that when I login, close the app, and open it again my app skips the login page and recognizes that I am already logged in. Although, I am now trying to install a logout button to a separate viewController. When clicked, this logout button needs to 1.) Reset UserDefaults.loginStatus to "False" 2.) Reset UserDefaults.username to nil 3.) Perform a segue to the login page.

Here is the related code from my ViewController.swift file. This is the first viewController which controls the loginPage.

import UIKit
import Firebase

let defaults = UserDefaults.standard

class ViewController: UIViewController {
func DoLogin(username: String, password: String) {
    //I Am not including a lot of the other stuff that takes place in this function, only the part that involves the defaults global variable
    defaults.setValue(username, forKey: "username")
    defaults.setValue("true", forKey: "loginStatus")
    defaults.synchronize()
    self.performSegue(withIdentifier: "loginToMain", sender: self) //This takes them to the main page of the app
}

override func viewDidLoad() {
    super.viewDidLoad()
    if let stringOne = defaults.string(forKey: "loginStatus") {
        if stringOne == "true" { //If the user is logged in, proceed to main screen
            DispatchQueue.main.async
                {
                    self.performSegue(withIdentifier: "loginToMain", sender: self)
            }
        }
    }

}

Below is my code in SecondViewController.swift, particularly the logout function.

import UIKit
import Firebase

class SecondViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
     if let username = defaults.string(forKey: "username") {
            checkAppSetup(username: username) //This is an unrelated function
            //I included this because this works fine. Proving that I am able to read the defaults variable fine from this other viewController
      }
}
@IBAction func logout(_ sender: Any) {
        defaults.setValue("false", forKey: "username")
        defaults.setValue("false", forKey: "loginStatus")
        defaults.synchronize()

        performSegue(withIdentifier: "logoutSegue", sender: nil)
    }

When the logout function is run, the segue performs fine but the default values do not change. Can someone explain why and what I can do to get around this?

**Side note, I am not actually going to set the defaults to "false" and "false". That is just temporary for while I am debugging this issue.


Solution

  • Several things.

    You should be using set(_:forKey:) and object(_:forKey) to read and write key/value pairs to defaults, not setValue(_:forKey). (Your use of defaults.string(forKey: "loginStatus") is correct, however.)

    You should probably be writing a nil to the userName key:

    defaults.set(nil, forKey: "username")
    

    And your logout IBAction should almost certainly be setting loginStatus to false, not true.

    Try changing those things.

    Also, there is no reason to call synchronize unless you are terminating your app in Xcode rather than pressing the home button on the device/simulator in order to let it exit normally.