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.
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)
You can store Bool, Float, Int, Object, Double or URL but not a Tuple. So you have two options, save two only hasPayrolAccess and hasPayrolAccess Bool values:
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "hasInventoryAccess")
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "hasPayrolAccess")
let hasInventoryAccess = NSUserDefaults.standardUserDefaults().boolForKey("hasInventoryAccess")
println(hasInventoryAccess)
let hasPayrolAccess = NSUserDefaults.standardUserDefaults().boolForKey("hasPayrolAccess")
println(hasPayrolAccess)
Or save it using an Array of Bool:
var accessLavels = [true,false]
println(accessLavels)
NSUserDefaults.standardUserDefaults().setValue(accessLavels, forKey: "accessLavels")
if let loadAccessLavels = NSUserDefaults.standardUserDefaults().arrayForKey("accessLavels") as? [Bool] {
if let hasInventoryAccess = loadAccessLavels.first {
println(hasInventoryAccess)
}
if let hasPayrolAccess = loadAccessLavels.last {
println(hasPayrolAccess)
}
}
I had a tuple with 3 values.
The following code was used for saving the tuple. Basically, I created a string from tuple (with components separated by a comma).
let defaultsLoad = NSUserDefaults.standardUserDefaults()
if appSingleton.runwayDestShared != nil
{
// Creating a String from the tuple
let runwayDestString = appSingleton.runwayDestShared!.0 + "," + appSingleton.runwayDestShared!.1 + "," + appSingleton.runwayDestShared!.2
defaultsLoad.setObject(runwayDestString, forKey: "RunwayDest")
}
To retrieve the tuple, I retrieved the string, broke it into array and used the array to re-create a tuple.
let runwayDestString = defaultsLoad.stringForKey("RunwayDest")
if let runwayDestString = runwayDestString
{
let runwayDestArray = runwayDestString.componentsSeparatedByString(",")
appSingleton.runwayDestShared = (runwayDestArray[0],runwayDestArray[1],runwayDestArray[2])
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With