1

I want to do like below with settar and getter:

  • if a variable already on memory, return it.
  • if a variable isn't load, load and return it.

Can you write it simply?

// Error code
class Person : NSObject {
    let personId : String
    init(personId: String) {
        self.personId = personId
    }
    public var name : String? {
        // The key is not static. It is decided dynamically.
        let keyName = "name-" + self.personId
        get {
            // If `name` exists, return it.
            if name != nil { return name }
            // Else load from `UserDefaults`
            return UserDefaults.standard.string(forKey: keyName)
        }
        set {
            name = UserDefaults.standard.set(newValue, forKey: keyName)
        }
    }
}
Hamish
  • 78,605
  • 19
  • 187
  • 280
Maiko Ohkawa
  • 853
  • 2
  • 11
  • 28

1 Answers1

3

You can't achieve what you are asking using only a variable, because computed properties don't have any storage in the instance. So you have to introduce a private variable to save the value in memory:

class Person : NSObject {
  public let personId : String
  private var _name: String?

  init(personId: String) {
    self.personId = personId
  }

  public var name : String? {
    get {
      let keyName = "name-" + self.personId
      return _name != nil ? _name : UserDefaults.standard.string(forKey: keyName)
    }

    set {
      let keyName = "name-" + self.personId
      UserDefaults.standard.set(newValue, forKey: keyName)
      _name = newValue
    }
  }
}
mugx
  • 9,869
  • 3
  • 43
  • 55
  • There's no need for `_name`. Just return `UserDefaults.standard.string(forKey: keyName)` in the getter. That's it. No need to check if it exists. – rmaddy Dec 13 '17 at 04:08
  • Maiko was asking for: "if a variable is already in memory", UserDefaults is not enough since https://stackoverflow.com/questions/37410584/ios-speed-of-reading-nsuserdefaults-vs-variables – mugx Dec 13 '17 at 04:20
  • Oh, I see, `computed properties` don't have any storage, I understood. Thank you. Yes, I didn't want to access `UserDefaults` every time because reading from disc was slow. – Maiko Ohkawa Dec 13 '17 at 05:54
  • Glad you found it useful. Feel free to upvote and accept the answer :) – mugx Dec 13 '17 at 05:55
  • @MaikoOhkawa But UserDefaults will not be read from disc every time. Don't worry about speed until you actually have a problem to deal with. – rmaddy Dec 13 '17 at 06:13
  • Oh, I see. `UserDefault` control access to disc properly. That's great. I use `UserDefault` directly, thanks rmaddy! If you know the documentation about it, I want to read. – Maiko Ohkawa Dec 13 '17 at 06:26
  • documentation is here: https://developer.apple.com/documentation/foundation/userdefaults also you may want to call `synchronize()`, after you write something inside `UserDefaults` https://developer.apple.com/documentation/foundation/userdefaults/1414005-synchronize – mugx Dec 13 '17 at 06:35
  • 1
    I had overlooked! `UserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value.` I had understood correctly and call `synchronize()`, thank you! – Maiko Ohkawa Dec 13 '17 at 06:40
  • 1
    The documentation says `synchronize()` is `unnecessary and shouldn't be used.` Recently it seems unnecessary. :) – Maiko Ohkawa Dec 13 '17 at 07:15
  • 1
    @MaikoOhkawa Regarding calling `synchronize()` - please see https://stackoverflow.com/questions/40808072/when-and-why-should-you-use-nsuserdefaultss-synchronize-method/40809748?s=1|43.0066#40809748 – rmaddy Dec 13 '17 at 23:06