在加载时从 NSUserDefault 加载开关状态

Loading a switch state from NSUserDefault on load

我正在为一个基本应用开发设置视图。基本,在用户的设置视图中只有一个开关。开关设置保存在 NSUserDefault 中。我使用委托将开关信号从设置视图发送到主视图。代表团工作正常。

UI 是基本的。在主视图上,标签将以绿色显示“打开”(如果开关打开)和“关闭”红色(如果开关关闭)。右上角有一个设置按钮,可以将 (settingsSegue) 转到设置 UITableViewController,UI开关所在的位置。

问题是在应用加载后加载 NSUserDefault。在 viewDidLoad 中,我检查是否为切换键保存了一个值。如果有,请加载它。如果不是,将其设置为 false(在故事板中,开关默认设置为 false。)开关状态每次都加载为关闭。即使默认值为开。这不应该发生。

ViewController.swift:

import UIKit

var nsDefaults = NSUserDefaults.standardUserDefaults()

class ViewController: UIViewController, SettingsViewControllerDelegate {

var onFromMain = Bool()

@IBOutlet weak var switchStateLabel: UILabel!


override func viewDidLoad() {
    super.viewDidLoad()

    if let mySavedKey = nsDefaults.objectForKey("savedSwitchSettingDefault") {
        // A value exists. Load it up.
        nsDefaults.objectForKey("savedSwitchSettingDefault")
        print("The switch is set! \(mySavedKey)")
        checkSwitchState()
    }
    else {
        // Nothing stored in NSUserDefaults yet. Set switch to False.
        nsDefaults.setBool(false, forKey: "savedSwitchSettingDefault")
        checkSwitchState()
    }

}


func myVCDidFinish(controller: SettingsViewController, switchState: Bool) {
    onFromMain = switchState.boolValue
    checkSwitchState()
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "settingsSegue" {
        let nav = segue.destinationViewController as! UINavigationController
        let secondVC = nav.topViewController as! SettingsViewController
        secondVC.delegate = self
    }
}


func checkSwitchState() {
    if onFromMain {
        switchStateLabel.text = "On"
        switchStateLabel.textColor = UIColor.greenColor()
    }
    else {
        switchStateLabel.text = "Off"
        switchStateLabel.textColor = UIColor.redColor()
    }
}


}

设置ViewController.swift:

import UIKit


protocol SettingsViewControllerDelegate {
func myVCDidFinish(controller: SettingsViewController, switchState: Bool)
}


class SettingsViewController: UITableViewController {


var delegate: SettingsViewControllerDelegate? = nil
@IBOutlet weak var switchOutlet: UISwitch!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    switchOutlet.on = nsDefaults.boolForKey("savedSwitchSettingDefault")
}

@IBAction func closeSettingsPageBarButtonItemPressed(sender: UIBarButtonItem) {

    if (delegate != nil) {
        delegate!.myVCDidFinish(self, switchState: switchOutlet.on)
        self.dismissViewControllerAnimated(true, completion: nil)
    }

}

@IBAction func switchPressed(sender: UISwitch) {
    // Tap the switch to change the setting.
    nsDefaults.setBool(switchOutlet.on, forKey: "savedSwitchSettingDefault")
}

}

我认为我的问题在于加载 "savedSwitchSettingDefault" 的默认密钥。这个对吗?还是问题出在代码的其他地方?

你可以根据你想要的默认值是 false 并且当密钥不存在时 boolForKey 给你 false 这样的事实来整理一下.

此外,通过访问 viewWillAppear 中的设置,您可以避免对委托回调的需要。

ViewController.swift

import UIKit

class ViewController: UIViewController {

    let nsDefaults = NSUserDefaults.standardUserDefaults()

    var onFromMain = false

    @IBOutlet weak var switchStateLabel: UILabel!

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        self.onFromMain = self.nsDefaults.boolForKey("savedSwitchSettingDefault")

        self.checkSwitchState()
    }   

    func checkSwitchState() {
        if self.onFromMain {
            switchStateLabel.text = "On"
            switchStateLabel.textColor = UIColor.greenColor()
        }
        else {
            switchStateLabel.text = "Off"
            switchStateLabel.textColor = UIColor.redColor()
        }
    }
}

设置ViewController.swift:

import UIKit

class SettingsViewController: UITableViewController {

    let nsDefaults = NSUserDefaults.standardUserDefaults()
    @IBOutlet weak var switchOutlet: UISwitch!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.switchOutlet.on = self.nsDefaults.boolForKey("savedSwitchSettingDefault")
    }

    @IBAction func closeSettingsPageBarButtonItemPressed(sender: UIBarButtonItem) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }

    @IBAction func switchPressed(sender: UISwitch) {
    // Tap the switch to change the setting.
        self.nsDefaults.setBool(self.switchOutlet.on, forKey: "savedSwitchSettingDefault")
    } 
}

从用户默认值中检索 bool 值时,如果该值不存在,boolForKey 将 return 为假。所以在这种情况下不需要展开。来自文档:

If a boolean value is associated with defaultName in the user defaults, that value is returned. Otherwise, false is returned.

如果正在设置值(您确定),并且应用程序的行为无法正常工作,则您的问题可能出在其他地方。

我建议使用另一种方法,将您的 "onFromMain" 声明为可选的布尔值,然后在需要时将其解包。

var onFromMain: Bool?

... 

func checkSwitchState() {
    //- This will unwrap your optional or set false if its nil
    let switchSate = onFromMain ?? false 
    //- Then you can set the values based on the value (or the default false)
    switchStateLabel.text = switchState ? "On" : "Off"
    switchStateLabel.textColor = switchState ? UIColor.greenColor() : UIColor.redColor()
}

然后在调试器上附加一个断点,看看该值是否正在解包或者它是否默认为 false。

此外,您仅在调用 segue 时才设置委托,这取决于具体情况,如果我理解正确的话,在您实际导航到设置视图之前,您可能不会获得该值。因此,当打开应用程序(不导航到设置视图)时,onFromMain 将永远不会被填充。

或者,您可以在加载应用程序时直接获取视图加载方法中的值。