I have the following test code:
func testSaveDictionary() {
let userDefaults = NSUserDefaults.standardUserDefaults()
var jo = [
"a" : "1.0",
"b" : "2.0"
]
let akey = "aKey"
userDefaults.setObject(jo, forKey: akey)
var isOk = userDefaults.synchronize()
var data0 = userDefaults.dictionaryForKey(akey)
println(data0)
}
The output of println(data0) is nil.
Anything wrong with my code? Is Swift Dictionary considered property list now or in the final release?
Update for Swift 2, Xcode 7: As @atxe noticed, NSUserDefaults dictionaries are now mapped as [String, AnyObject]
. This is a
consequence of the Objective-C "lightweight generics" which allow
to declare the Objective-C method as
- (NSDictionary<NSString *,id> *)dictionaryForKey:(NSString *)defaultName
(Default objects must be property lists and in particular the dictionary
keys can only be strings.)
On the other hand, a Swift dictionary is bridged automatically if possible, so the original code from the question works (again):
let jo = [
"a" : "1.0",
"b" : "2.0"
]
let akey = "aKey"
// Swift 2:
userDefaults.setObject(jo, forKey: akey)
// Swift 3:
userDefaults.set(jo, forKey: akey)
Original answer for Swift 1.2:
The user defaults can store NSDictionary
objects. These are mapped to Swift
as [NSObject : AnyObject]
:
var jo : [NSObject : AnyObject] = [
"a" : "1.0",
"b" : "2.0"
]
userDefaults.setObject(jo, forKey: akey)
var isOk = userDefaults.synchronize()
And note that dictionaryForKey()
returns an optional, so you should check it
for example with an optional assignment:
if let data0 = userDefaults.dictionaryForKey(akey) {
print(data0)
} else {
print("not set")
}
// Output: [b: 2.0, a: 1.0]
You need to convert it into NSData
first. Something like this:
var data = NSKeyedArchiver.archivedDataWithRootObject(jo)
var userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(data, forKey:akey)
I faced with this problem yesterday and filed a radar: Cannot store Dictionary in NSUserDefaults in iOS8. This issue is related only to iOS 8. Also I described a workaround for this case: Workaround for saving dictionary in NSUserDefaults. Works like a charm.
/// Save
NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(object), forKey: key)
/// Read
var data = NSUserDefaults.standardUserDefaults().objectForKey(key) as NSData
var object = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [String: String]
Follow this beautiful code below -> Swift 3
public func setDict(dict: NSDictionary) {
let data = NSKeyedArchiver.archivedData(withRootObject: dict)
let userDefaults = UserDefaults.standard
userDefaults.set(data, forKey:"keyHere")
}
public func getDict() -> NSDictionary {
let data = UserDefaults.standard.object(forKey: "keyHere") as! NSData
let object = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as! NSDictionary
return object;
}
//swift 4.0
//for saving
let userDefaults = UserDefaults.standard
userDefaults.setValue(value, forKey: "Your_Key")
userDefaults.synchronize()
//for for retrieve
let loadedCart = UserDefaults.standard.dictionary(forKey: "Your_Key")