Search code examples
iosswiftios8tuplesnsuserdefaults

Save a tuple in NSUserDefaults


I'm using a tuple to store something like this.

var accessLavels: (hasInventoryAccess: Bool, hasPayrolAccess: Bool)
accessLavels = (hasInventoryAccess: true, hasPayrolAccess: false)

Now I want to save it in NSUserDefaults.

NSUserDefaults.standardUserDefaults().setValue(accessLavels, forKey: "AccessLevelKey")
NSUserDefaults.standardUserDefaults().synchronize()

But I get the following error.

Type '(hasInventoryAccess: Bool, hasPayrolAccess: Bool)' does not conform to protocol 'AnyObject'

How can I resolve this issue? If its impossible, then any other suggestions to save a tuple is welcome.

Thank you.


Solution

  • I encountered a similar scenario trying to encode a tuple with NSCoder. The way I am solving it is by manually converting the tuple to a Dictionary. This is not a great solution as the keys need to be changed in several places if the tuple ever changes.

    I had a nested enum in my tuple and gave it a base type (String) from which I converted the raw value. It was a little extra work but thankfully yours is only primitives.

    # SerializeableTuple.swift
    
    typealias AccessTuple = (hasInventoryAccess: Bool, hasPayrolAccess: Bool)
    typealias AccessDictionary = [String: Bool]
    
    let InventoryKey = "hasInventoryAccess"
    let PayrollKey = "hasPayrollAccess"
    
    func serializeTuple(tuple: AccessTuple) -> AccessDictionary {
        return [
            InventoryKey : tuple.hasInventoryAccess,
            PayrollKey : tuple.hasPayrolAccess
        ]
    }
    
    func deserializeDictionary(dictionary: AccessDictionary) -> AccessTuple {
        return AccessTuple(
            dictionary[InventoryKey] as Bool!,
            dictionary[PayrollKey] as Bool!
        )
    }
    

    # Encoding / Decoding
    
    var accessLavels: AccessTuple = (hasInventoryAccess: true, hasPayrolAccess: false)
    
    // Writing to defaults
    let accessLevelDictionary = serializeTuple(accessLavels)
    NSUserDefaults.standardUserDefaults().setObject(accessLevelDictionary, forKey: "AccessLevelKey")
    
    // Reading from defaults
    let accessDic = NSUserDefaults.standardUserDefaults().dictionaryForKey("AccessLevelKey") as AccessDictionary
    let accessLev = deserializeDictionary(accessDic)