I have an [Int:Bool]
dictionary and I am trying to save it into my NSDictionary.. However, it crashes with error Attempt to set a non-property-list object
let dictionary = [Int:Bool]()
self.dictionary[2] = true
self.dictionary[3] = false
NSUserDefaults.standardUserDefaults().setObject(dictionary, forKey: "dictionary")
Also, for loading, first I tried this but error logged it strictly requires AnyObject?.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary")
Then I tried this and it logged:
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool]
I also tried dictionaryForKey
. I got..
NSUserDefaults.standardUserDefaults().dictionaryForKey("dictionary")
Cannot assign value to type [String: AnyObject] to type [Int:Bool]
So which one of these 2 is a better approach to take? (The values would be optional in my case I think)
1.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool] ?? [Int:Bool]()
2.
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool])!
Among basic types, UserDefaults
can save any object that conforms to Codable
protocol. Dictionary
is one of the types that implements this protocol. You don't even need to write any custom code:
let dictionary = ["name": "Adam"]
// Save to User Defaults
UserDefaults.standard.set(dictionary, forKey: "names")
// Read from User Defaults
let saved = UserDefaults.standard.value(forKey: "names") as? [String: String]
See more info about Codable
You can use UserDefaults
to save a Dictionary
as long as key and value types are types that can be represented in a plist format (NSNumber
, Data
, etc.). If that's not the case, we can always serialise other types to Data
when writing and deserialise from Data
when reading. It can be accomplished with pretty simple extension of UserDefaults
using NSKeyArchiver
:
extension UserDefaults {
/// Save dictionary on key
open func set<Key, Value>(dictionary: [Key: Value]?, forKey key: String) {
let data = NSKeyedArchiver.archivedData(withRootObject: dictionary as Any)
set(data, forKey: key)
}
// Retrieve dictionary for key
open func dictionary<Key, Value>(forKey key: String) -> [Key: Value]? {
guard let data = object(forKey: key) as? Data else { return nil }
return NSKeyedUnarchiver.unarchiveObject(with: data) as? [Key: Value]
}
}
Now you can call these methods:
let ages = ["Adam": 25]
// Save
UserDefaults.standard.set(dictionary: ages, forKey: "ages")
// Read
let saved: [String: Int]? = UserDefaults.standard.dictionary(forKey: "ages")
print(saved) // Optional(["Adam": 25])
Save custom data
func setCustomDictionary(dict: [Int: Bool]) {
let keyedArch = NSKeyedArchiver.archivedDataWithRootObject(dict)
NSUserDefaults.standardUserDefaults().setObject(keyedArch, forKey: "dictionary")
}
Retrieve data
func getDictionary() -> [Int: Bool]? {
let data = NSUserDefaults.standardUserDefaults().objectForKey("dict")
let object = NSKeyedUnarchiver.unarchiveObjectWithData(data as! NSData)
return object as? [Int: Bool]
}
Usage
var customDictionary = [Int: Bool]()
customDictionary[2] = true
customDictionary[3] = false
// Store data in NSUserDefaults
setCustomDictionary(customDictionary)
// Get data from NSUserDefaults
let userDefaultsDictionary = getDictionary()
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