Dev0urCode
Dev0urCode

Reputation: 83

UserDefaults checking for nil value not working

Any idea why my if statement always gives else answer? I noticed from the print that the object is stored as "optional()", maybe this optional state is different from nil?

class ViewController: UIViewController {

    @IBOutlet weak var phoneLabel: UITextField!
    @IBOutlet weak var phoneDisplayLabel: UILabel!

    @IBAction func storeButton(_ sender: Any) {
        UserDefaults.standard.removeObject(forKey: "Nb")
        UserDefaults.standard.set("\(phoneLabel.text!)", forKey: "Nb")
        print(UserDefaults.standard.object(forKey: "Nb") as Any)
    }

    @IBAction func retrieveButton(_ sender: Any) {
        let phoneNB = UserDefaults.standard.value(forKey: "Nb")
        if let phoneNbDisplay = phoneNB as? String {
            if UserDefaults.standard.object(forKey: "Nb") != nil {
                phoneDisplayLabel.text = "Your NB is \(phoneNbDisplay)"
            }
            else {
                phoneDisplayLabel.text = "enter a number first"
            }
        }
    }
}

Upvotes: 0

Views: 2482

Answers (4)

DJ_Mobi90
DJ_Mobi90

Reputation: 131

You might forget to call synchronize while storing value.You can try this.

@IBAction func storeButton(_ sender: Any) {
    UserDefaults.standard.removeObject(forKey: "Nb")
    UserDefaults.standard.set("\(phoneLabel.text!)", forKey: "Nb")
    UserDefaults.standard.synchronize()

    print (UserDefaults.standard.object(forKey: "Nb") as Any)
}

@IBAction func retrieveButton(_ sender: Any) {
    if let phoneNB = UserDefaults.standard.string(forKey: "Nb"){
         phoneDisplayLabel.text = "Your NB is \(phoneNB)"
    }else {
         phoneDisplayLabel.text = "enter a number first"
    }
}

Upvotes: -1

vadian
vadian

Reputation: 285064

The recommended way (by Apple!) is to register key/value pairs in UserDefaults to provide – as the class name implies – default values. Those default values are considered until the value is changed the first time.

The Swift benefit is that there is always a (non-optional) value which can be unwrapped safely.

As soon as possible (e.g. applicationWillFinishLaunching) add these lines. They are supposed to be executed every time the application launches. The key Nb is registered with an empty string default value.

let defaultValues = ["Nb" : ""]
UserDefaults.standard.register(defaults: defaultValues)

In storeButton don't remove the key and don't use String Interpolation for a String but check if the text property is nil and save an empty string in this case. The print line is nonsensical because reading from UserDefaults right after writing will not get the changes and you know what's been written

@IBAction func storeButton(_ sender: Any) {
    UserDefaults.standard.set(phoneLabel.text ?? "", forKey: "Nb")
}

In retrieveButton get the string with the dedicated method string(forKey, unwrap it (due to registering the key there is always a value) and only check for empty string. And don't read the (same) value 3 times.

@IBAction func retrieveButton(_ sender: Any) {

    let phoneNbDisplay = UserDefaults.standard.string(forKey: "Nb")!
    if phoneNbDisplay.isEmpty {
        phoneDisplayLabel.text = "enter a number first"
    } else {
        phoneDisplayLabel.text = "Your NB is \(phoneNbDisplay)"
    }
}

Upvotes: 2

Divyesh Gondaliya
Divyesh Gondaliya

Reputation: 904

try this

if (UserDefaults.standard.value(forKey: "etc") != nil)
{
    if (UserDefaults.standard.value(forKey: "etc") as! String).character.count == 0
    {
        //value is ""
    }else{
        //having some value
    }
}

enter image description here

Upvotes: 0

OOPer
OOPer

Reputation: 47886

As vadian commented, you should not and have no need to use KVC method value(forKey:) in this case.

Try this:

@IBAction func storeButton(_ sender: Any) {
    UserDefaults.standard.removeObject(forKey: "Nb")
    UserDefaults.standard.set(phoneLabel.text ?? "", forKey: "Nb") //<-You have no need to use String Interpolation.
    print (UserDefaults.standard.object(forKey: "Nb") as Any)
}

@IBAction func retrieveButton(_ sender: Any) {
    if let phoneNB = UserDefaults.standard.string(forKey: "Nb") {
        if !phoneNB.isEmpty {
            phoneDisplayLabel.text = "Your NB is \(phoneNB)"
        } else {
            phoneDisplayLabel.text = "enter a number first"
        }
    } else {
        //### What do you want to do if "Nb" is not set?
    }
}

Upvotes: 1

Related Questions