1

When I try to save to NSUserDefaults by adding a setter to my class variable (in this case the id and authToken variables, the values don't seem to be saved. When I run with a breakpoint on, the getter of id and authToken always return nil even after setting them with a value.

class CurrentUser {

    static let defaultInstance = CurrentUser()

    func updateUser(id id: String, authToken: String) {
        self.id = id
        self.authToken = authToken
    }

    var authToken: String? {
        get {
            if let authToken = NSUserDefaults.standardUserDefaults().objectForKey("userAuthToken") {
                return (authToken as! String)
            } else {
                return nil
            }
        }
        set {
            NSUserDefaults.standardUserDefaults().setObject(authToken, forKey: "userAuthToken")
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }

    var id: String? {
        get {
            if let id = NSUserDefaults.standardUserDefaults().objectForKey("userId") {
                return (id as! String)
            } else {
                return nil
            }
        }
        set {
            NSUserDefaults.standardUserDefaults().setObject(id, forKey: "userId")
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }
}

However, when I pull the lines out to the updateUser function (one level higher), all works as expected.

class CurrentUser {

    static let defaultInstance = CurrentUser()

    func updateUser(id id: String, authToken: String) {
        NSUserDefaults.standardUserDefaults().setObject(id, forKey: "userId")
        NSUserDefaults.standardUserDefaults().synchronize()

        NSUserDefaults.standardUserDefaults().setObject(authToken, forKey: "userAuthToken")
        NSUserDefaults.standardUserDefaults().synchronize()
    }

    var authToken: String? {
        get {
            if let authToken = NSUserDefaults.standardUserDefaults().objectForKey("userAuthToken") {
                return (authToken as! String)
            } else {
                return nil
            }
        }
    }

    var id: String? {
        get {
            if let id = NSUserDefaults.standardUserDefaults().objectForKey("userId") {
                return (id as! String)
            } else {
                return nil
            }
        }
    }
}

Why would this be? What am I missing? Does the { set } run on a different thread / mode where NSUserDefaults isn't accessible?

Alex
  • 5,298
  • 4
  • 29
  • 34
  • Why not load/save during object lifetime and keep them as simple instance variables? It's over-engineered. – Droppy Jun 15 '16 at 14:51
  • @Droppy Can you explain a bit more what you mean by that. – Alex Jun 15 '16 at 14:55
  • Load the values during init and save during dealloc (or whatever its called in swift) and just keep the values as normal instance variables. Alternatively have explicit load/save methods. I doubt there is a need to sync to user-defaults every time they change. – Droppy Jun 15 '16 at 14:57
  • You are using the variables as computed variables, so they don't actually have a value storage location. So when you do `NSUserDefaults.standardUserDefaults().setObject(id, forKey: "userId")`, `id` doesn't really exist... Change that to `NSUserDefaults.standardUserDefaults().setObject(newVal, forKey: "userId")` – Putz1103 Jun 15 '16 at 15:16

2 Answers2

1

You must use newValue inside set method, value is still nil, or use didSet and then you can use variable.

tbilopavlovic
  • 1,096
  • 7
  • 13
0

As Alex said, you must use newValue in set method. Moreover, you can refer to this link for more detail: Store [String] in NSUserDefaults (Swift)

Community
  • 1
  • 1
Thanh Pham
  • 75
  • 2