Search code examples
iosswiftnsuserdefaults

Swift NSUserDefaults not getting set


I don't like to ask simple questions but today I am stumped. All I need to do is see if there is a value set in NSUserdefaults on app launch. If it is not then add a value. That's it. Every time I launch my app I get this as results

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
    {

        let defaults = NSUserDefaults.standardUserDefaults()
        var returnValue: [String]? = NSUserDefaults.standardUserDefaults().objectForKey("BGColorStr") as? [String]

        println("returnValue: \(returnValue) ...")

        if (returnValue == nil)
        {
            println("Value is nil")
            defaults.setObject("Default", forKey:"BGColorStr")
            defaults.synchronize()
        }
        else
        {
            println("Value is NOT nil")
        }


        // Override point for customization after application launch.
        return true
    }

returnValue: nil ...
Value is nil

Solution

  • When you call setObject you're setting a string:

    defaults.setObject("Default", forKey:"BGColorStr")
    

    When you are retrieving the value, you are attempting to cast it into an optional array of strings:

    var returnValue: [String]? = NSUserDefaults.standardUserDefaults().objectForKey("BGColorStr") as? [String]
    

    The as? operator sets returnValue to nil because the types don't match.

    You're also using var instead of let when you don't need to, and not using the new if let… Swift syntax.

    Try this instead: (last updated for Swift 2 / Xcode 7 Beta 3)

    let defaults = NSUserDefaults.standardUserDefaults()
    let key = "BGColorStr"
    
    if let storedValue = defaults.objectForKey(key) as? String {
        print("Value is NOT nil: \(storedValue)")
    } else {
        print("Value is nil")
        defaults.setObject("Default", forKey:key)
        defaults.synchronize()
    }
    

    If you find yourself doing this a lot, you can encapsulate the logic into an NSUserDefaults extension:

    extension NSUserDefaults {
        func objectForKey(defaultName: String, defaultValue: AnyObject) -> AnyObject {
            var obj = objectForKey(defaultName)
    
            if obj == nil {
                obj = defaultValue
                setObject(obj, forKey: defaultName)
            }
    
            return obj!
        }
    }
    

    Then to read a value:

    let returnValue = NSUserDefaults
        .standardUserDefaults()
        .objectForKey("BGColorStr", defaultValue: "Default")
    
    // returnValue is either the stored value or "Default"