Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从其他ViewController访问Swift中的用户默认值_Ios_Swift_Uiviewcontroller_Nsuserdefaults_Userdefaults - Fatal编程技术网

Ios 从其他ViewController访问Swift中的用户默认值

Ios 从其他ViewController访问Swift中的用户默认值,ios,swift,uiviewcontroller,nsuserdefaults,userdefaults,Ios,Swift,Uiviewcontroller,Nsuserdefaults,Userdefaults,在我的应用程序中,我使用UserDefaults存储用户的登录状态(无论他们是否登录)及其用户名。它的工作原理很好,当我登录时,关闭应用程序,然后再次打开它。我的应用程序跳过登录页面,并识别我已经登录。不过,我现在正在尝试将注销按钮安装到单独的viewController。单击时,此注销按钮需要1.)将UserDefaults.loginStatus重置为“False”2.)将UserDefaults.username重置为nil 3.)执行登录页面的切换 以下是我的ViewController

在我的应用程序中,我使用UserDefaults存储用户的登录状态(无论他们是否登录)及其用户名。它的工作原理很好,当我登录时,关闭应用程序,然后再次打开它。我的应用程序跳过登录页面,并识别我已经登录。不过,我现在正在尝试将注销按钮安装到单独的viewController。单击时,此注销按钮需要1.)将UserDefaults.loginStatus重置为“False”2.)将UserDefaults.username重置为nil 3.)执行登录页面的切换

以下是我的ViewController.swift文件中的相关代码。这是第一个控制登录页面的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”。在我调试此问题时,这只是暂时的

有几件事

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

您可能应该将nil写入用户名密钥:

defaults.set(nil, forKey: "username")
您的注销
iAction
几乎肯定应该将
loginStatus
设置为
false
,而不是
true

试着改变这些事情

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

有几件事

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

您可能应该将nil写入用户名密钥:

defaults.set(nil, forKey: "username")
您的注销
iAction
几乎肯定应该将
loginStatus
设置为
false
,而不是
true

试着改变这些事情


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

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

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

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

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

这里是
defaults.setValue(“true”,forKey:“loginStatus”)
您正在设置
true
。对吗?为了调试的目的?我想应该是
false
是的,这是我问这个问题时的一个打字错误。在真正的代码中,它确实会说“false”。非常感谢。但是无论哪种方式,当我在ViewController中访问它时,在SecondViewController中设置它的任何内容都不会出现。Swift您可以在这一行
performsgue(带有标识符:“logoutSegue”,发件人:nil)
上设置断点,然后在控制台中键入:
po UserDefaults.standard.value(forKey:“loginStatus”)
并查看它将返回什么
true
false
?我相信Duncan C回答了我下面的问题,我只需要使用.set(u,forKey:“”)而不是.setValue。但是谢谢你的主意!这里是
defaults.setValue(“true”,forKey:“loginStatus”)
您正在设置
true
。对吗?为了调试的目的?我想应该是
false
是的,这是我问这个问题时的一个打字错误。在真正的代码中,它确实会说“false”。非常感谢。但是无论哪种方式,当我在ViewController中访问它时,在SecondViewController中设置它的任何内容都不会出现。Swift您可以在这一行
performsgue(带有标识符:“logoutSegue”,发件人:nil)
上设置断点,然后在控制台中键入:
po UserDefaults.standard.value(forKey:“loginStatus”)
并查看它将返回什么
true
false
?我相信Duncan C回答了我下面的问题,我只需要使用.set(u,forKey:“”)而不是.setValue。但是谢谢你的主意!那很有效!如果您不介意解释的话,.set和.setValue之间到底有什么区别?此外,.synchronize究竟是做什么的呢?
setValue:forKey:
函数是一种KVC(键值编码)方法,适用于任何NSOb