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)

+3


source to share


2 answers


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) }
    }
}

      

+5


source


If you are using swift in an iOS or OS X context, then NSUserDefaults is the ABSOLUTELY correct way to do it.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html



http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/

+1


source







All Articles