2017-03-05 91 views
0

在我的应用程序中,我使用UserDefaults来存储用户的登录状态(不管他们是否已登录)以及他们的用户名。它工作正常,当我登录时,关闭应用程序,并再次打开我的应用程序跳过登录页面,并认识到我已经登录。虽然,我现在试图安装一个注销按钮到一个单独的viewController。单击时,此注销按钮需要1.)将UserDefaults.loginStatus重置为“False”2.)将UserDefaults.username重置为零3.)对登录页面执行segue。在其他视图控制器中访问Swift中的UserDefaults

以下是我的ViewController.swift文件中的相关代码。这是控制loginPage的第一个viewController。

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) 
      } 
     } 
    } 

} 

以下是我在SecondViewController.swift中的代码,特别是注销功能。

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) 
    } 

注销函数运行时,segue执行正常,但默认值不会更改。有人可以解释为什么和我能做些什么来解决这个问题吗?

**注意,我实际上不会将默认值设置为“false”和“false”。这只是暂时的,因为我正在调试这个问题。

+1

这里'defaults.setValue(“真”,forKey:“登录状态“)'你正在设置'true'。这是对的吗?为了调试目的?我猜它应该是'false' –

+0

是的,这是我提出这个问题时的一个错误。在真实的代码中它确实会说“错误”。谢谢。但无论哪种方式,无论我在SecondViewController中设置它,在ViewController.swift –

+0

中访问它时都不会出现。您可以在此行上设置断点“performSegue(withIdentifier:”logoutSegue“,sender:nil)'并在控制台中输入:'po UserDefaults.standard.value(forKey:“loginStatus”)'看看它会返回“true”还是“false”? –

回答

2

几件事。

您应该使用set(_:forKey:)object(_:forKey)将键/值对读取和写入默认值,而不是setValue(_:forKey)。 (您使用的defaults.string(forKey: "loginStatus")是正确的,但是。)

或许你也应该写一个零到用户名输入键:

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

和你注销IBAction应该几乎可以肯定是设置loginStatusfalse,不true

尝试改变这些东西。

此外,没有理由调用同步,除非您在Xcode中终止您的应用程序,而不是按设备/模拟器上的主页按钮以使其正常退出。

+0

完美的工作!如果你不介意解释,.set和.setValue之间的区别究竟是什么?而且,什么是.synchronize呢? –

+0

'setValue:forKey:'函数是一个KVC(键值编码)方法,它可以在任何NSObject上设置它的值。我不认为它与'UserDefaults'正常工作。 '.synchronize'函数强制'UserDefaults'立即写入磁盘。这是相对昂贵的,所以如果您的应用可能会在它有机会将更改保存到默认值之前终止,则应该只使用它(例如,如果您在Xcode中按命令周期以在开发期间杀死应用程序,或者如果您使用force-quit从跳板。) –

+0

了解。感谢伟大的回答和优秀的解释! –

1

嘿我最近使用完全相同的概念:

1)在初始视图,在viewDidLoad(),检查是否有人已经登录与否,并且只有一个用户可以在一个装置在一个记录时间,所以我们检查像

let defaults = UserDefaults.standard 
if defaults.object(forKey: "userName") != nil && defaults.object(forKey: "userPassword") != nil 
    { 
      let loginObject = self.storyboard?.instantiateViewController(withIdentifier: "YourSecondViewController") as! YourSecondViewController 
//As someone's details are already saved so we auto-login and move to second view  
}} 

2)在您的登录按钮的功能,请检查你想要的任何条件检查,然后,里面的一样,如果条件满足,然后将数据保存到userDefaults。

// If no details are saved in defaults, then control will come to this part, where we will save the entered userName and Password 

    let defaults = UserDefaults.standard 
    defaults.set(self.enteredUseName, forKey: "userName") 
    defaults.set(self.enteredPassword, forKey: "Password") 
    defaults.synchronize() 

3)在退出按钮,删除userDefaults并再次装入登录视图:

let defaults = UserDefaults.standard 
defaults.removeObject(forKey: "userName") //We Will delete the userDefaults 
defaults.removeObject(forKey: "userPassword") 
defaults.synchronize() //Sync. the defaults. 
navigationController?.popToRootViewController(animated: true) //Move Back to initial view. 

4)如果使用导航控制,你必须是使用:P,那么你将想必看到后面按钮,如果点击它会打开第二个观点,对于您可以隐藏导航栏登录鉴于viewDidLoad()

self.navigationController?.navigationBar.isHidden = true 
相关问题