Saving Dictionary into Nsuserdefaults

Swift NSUserDefaults not saving Dictionary?

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]

Save and Load Custom Dictionary - NSUserDefaults

Swift 4

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

Swift 3

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

Swift 2

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

How to Store multiple dictionary in NSUserDefaults

Every time you are using the same key and replacing the existing dictionary object...

// Using the same key will overwrite the last saved dictionary.
[[NSUserDefaults standardUserDefaults] setObject:discRege forKey:@"ABC"];

Instead of storing it as a dictionary, store it as an array of dictionaries. Whenever you add new registration, fetch the saved array, add new dictionary object into it and update the userDefaults with that array.

mutableArray = [[[NSUserDefaults standardUserDefaults]objectForKey:@"ABC"] mutableCopy];
[mutableArray addObject:discReg];
[[NSUserDefaults standardUserDefaults] setObject:mutableArraay forKey:@"ABC"];
[[NSUserDefaults standardUserDefaults] synchronize];

Hope it helps.

Save Dictionary into NSUserDefaults Swift

I managed to save my custom Dictionary using Realm!
Instead of a struct I use a different class like this:

import RealmSwift

class Sensors : Object {

dynamic var sensorName = ""
dynamic var sensorType = ""
dynamic var sensorSub = ""

}

and then I fill it like this:

    var useOfRealm = try! Realm() 
var allSensors = useOfRealm.objects(Sensors.self)
var saving = Sensors()
func fillThis() {
try! useOfRealm.write {

saving.sensorName = "something"
saving.sensorType = "something"
saving.sensorSub = "something"

useOfRealm.add(saving)
}
}

Use the function with parameters so you can fill the 'Dictionary' Dynamically.

Use allSensors so you can retrieve everything that you want.

Save dictionary in userdefaults in swift 3 with xcode 8

This problem seems to be caused by having two versions of xcode/simulator installed.

What worked for me was uninstalling xcode 7 and just keeping xcode 8 beta on my system. Emptying trash, resetting the simulator and running. I also restarted my computer.

After following these steps the simulator is able to save to UserDefaults.

Saving dictionary into NSUserDefaults

From the NSUserDefaults documentation:

The value parameter can be only property list objects: NSData,
NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and
NSDictionary objects, their contents must be property list objects.
See “What is a Property List?” in Property List Programming Guide.

You cannot store a dictionary with elements of Element in the dictionary.

One option is to make sure Element implements the NSCoding protocol and then use NSKeyedArchiver to convert your dictionary into NSData:

// Storing the dictionary
var data = NSKeyedArchiver.archivedDataWithRootObject(theDict)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: tableViewData)

// Retrieving the dictionary
var outData = NSUserDefaults.standardUserDefaults().dataForKey(tableViewData)
var dict = NSKeyedUnarchiver.unarchiveObjectWithData(outData)

Your protocol implementation would look like something like this:

init(coder aDecoder: NSCoder!) {
self.state = State.fromRaw(aDecoder.decodeObjectForKey("state") as String)
}

func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(self.state.toRaw(), forKey: "state")
}

You cannot store an Enum, but you can store the raw representation of it which is a string.

Save dictionary to UserDefaults

Dictionaries are Codable objects by default, you can use the following extensions to save them to UserDefaults

extension UserDefaults {
func object<T: Codable>(_ type: T.Type, with key: String, usingDecoder decoder: JSONDecoder = JSONDecoder()) -> T? {
guard let data = self.value(forKey: key) as? Data else { return nil }
return try? decoder.decode(type.self, from: data)
}

func set<T: Codable>(object: T, forKey key: String, usingEncoder encoder: JSONEncoder = JSONEncoder()) {
let data = try? encoder.encode(object)
self.set(data, forKey: key)
}
}

They can be used like this:

let test = [1:"me"]
UserDefaults.standard.set(object: test, forKey: "test")

let testFromDefaults = UserDefaults.standard.object([Int: String].self, with: "test")

This extension and many others are part of SwifterSwift, you might want to use it for your next iOS project :)

How do I save NSUserDefaults when dictionary key has a Null value

formValues returns NSNull for empty values which can't be saved in NSDictionary as noted by Paulw11.

You can use this function to filter it.

let filtered = message.filter({!$1.isKindOfClass(NSNull)}).reduce([:]) { ( dic , e) -> [String:AnyObject] in
var dic = dic
dic[e.0 as! String] = e.1
return dic
}

and then save the filtered in userDefaults



Related Topics



Leave a reply



Submit