Repeating getter code quickly
I am trying to have variables in swift that are critical user settings for an application, so they need to persist to disk after every change. There are a small number of these variables, and I am happy that the first read is from disk after the application starts.
I have some code similar to this:
var _myEnumMember:MyEnum?
var myEnumMember:MyEnum {
get {
if let value = _myEnumMember { // in memory
return value
}
var c:Cache = Cache()
var storedValue:MyEnum? = c.get("SomeStorageKey");
if let value = storedValue { // exists on disk
self.myEnumMember = value // call setter to persist
return self.myEnumMember // call getter again with value set
}
self.myEnumMember = .DefaultValue // assign via setter
return self.rankingDuration // call getter after `set`
}
set (newValue){
self._myEnumMember = newValue // assign to memory
var c:Cache = Cache()
c.put("SomeStorageKey", data: ser) // store in disk
}
I have about 5-6 properties to do this - I don't want to repeat myself over and over again - is there a way to DRY this code so I don't have to repeat this logic in multiple places?
(Note: ask here, not CR.SE, because I would like to get answers to explain how DRY getters / setters in these situations, and not get criticized for a certain piece of code)
source to share
I've been working on something similar recently - this might be your best bet. I used this as nested struct
, but doesn't have to be nested.
First, define a type LocalCache
that will handle persisting your properties:
struct LocalCache {
// set up keys as constants
// these could live in your class instead
static let EnumKey = "EnumKey"
static let IntKey = "IntKey"
static let StringKey = "StringKey"
// use a single cache variable, hopefully?
var cache = Cache()
// in-memory values go in a Dictionary
var localValues: [String: Any] = [:]
// fetch from local storage or from disk
// note that the default value also sets the return type
mutating func fetch<T>(key: String, defaultValue: T) -> T {
if localValues[key] == nil {
localValues[key] = cache.get(key) ?? defaultValue
}
return localValues[key]! as T
}
// save in both local storage and to disk
mutating func store(key: String, _ value: Any) {
localValues[key] = value
cache.put(key, data: value)
}
}
Then add an instance LocalCache
to your class and you can have much simpler getter / setters.
class Test {
// instance of the local cache
var localCache = LocalCache()
var enumPropery: MyEnum {
get { return localCache.fetch(LocalCache.EnumKey, defaultValue: MyEnum.DefaultValue) }
set { localCache.store(LocalCache.EnumKey, newValue) }
}
var intProperty: Int {
get { return localCache.fetch(LocalCache.IntKey, defaultValue: 0) }
set { localCache.store(LocalCache.IntKey, newValue) }
}
var stringProperty: String {
get { return localCache.fetch(LocalCache.StringKey, defaultValue: "---") }
set { localCache.store(LocalCache.StringKey, newValue) }
}
}
source to share
If you are using swift in an iOS or OS X context, then NSUserDefaults is the ABSOLUTELY correct way to do it.
http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/
source to share