问题
I am trying to add a key and a value to a dictionary then add this dictionary the user defaults and read back into a dictionary object. I have two questions that I would really appreciate any help in,
1) why is the dictionary being read from user defaults empty? Since I added a key and a value to the dictionary shouldn't those be saved to the dictionary I retrieve from user defaults?
let defaults = UserDefaults.standard;
var myDict = [String: String]()
myDict["key"] = "value"
defaults.setValue(myDict, forKey: "myDict")
let mydict2 = defaults.object(forKey: "myDict") as? [String: String] ?? [String:String]()
print(mydict2)
2) What can I do to this code if the dictionary stores a custom class that I created as a value or a key so if the dictionary was like this:
class Car {
var engineSize: Int
var color: String
init() {
engineSize = 2000
color = "blue"
}
}
class Boat {
var surfaceArea: Int
var weight: Int
init() {
surfaceArea = 3500
weight = 4000
}
}
var myDict = [Car: Boat]()
how can I save that second dict to user defaults and read it from there?
Thank you
EDIT:
This is the answer suggested by ebby94:
var myDict = [String:String]()
myDict["key"] = "value";
let data = NSKeyedArchiver.archivedData(withRootObject: myDict)
UserDefaults.standard.set(data, forKey: "myDict")
func foo()
{
guard let archivedData = UserDefaults.standard.value(forKey: "myDict") as? Data
else
{
print("failed1")
return
}
guard var unarchivedDictionary = NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? [String:String]
else
{
print("failed2")
return
}
print(unarchivedDictionary["key"]!)
}
foo()
However this prints failed1, I'm assuming the data wasn't archived correctly. Can this be because I'm running it in playground?
回答1:
If you want to save custom object to userDefault first you need to encode & decode variable then save using archive & get data using unarchive.
class Car {
var engineSize: Int
var color: String
init() {
engineSize = 2000
color = "blue"
}
// Decode
required convenience public init(coder decoder: NSCoder)
{
self.init()
if let engineSize = decoder.decodeObject(forKey: "engineSize") as? Int
{
self.engineSize = engineSize
}
if let color = decoder.decodeObject(forKey: "color") as? String
{
self.color = color
}
}
// Encode
func encodeWithCoder(coder : NSCoder)
{
if let engineSize = self.engineSize
{
coder.encode(engineSize, forKey: "engineSize")
}
if let color = self.color
{
coder.encode(color, forKey: "weight")
}
}
}
class Boat {
var surfaceArea: Int
var weight: Int
init() {
surfaceArea = 3500
weight = 4000
}
// Decode
required convenience public init(coder decoder: NSCoder)
{
self.init()
if let surfaceArea = decoder.decodeObject(forKey: "surfaceArea") as? Int
{
self.surfaceArea = surfaceArea
}
if let weight = decoder.decodeObject(forKey: "weight") as? Int
{
self.weight = weight
}
}
// Encode
func encodeWithCoder(coder : NSCoder)
{
if let surfaceArea = self.surfaceArea
{
coder.encode(surfaceArea, forKey: "surfaceArea")
}
if let weight = self.weight
{
coder.encode(weight, forKey: "weight")
}
}
回答2:
You can't save a dictionary directly in UserDefaults
. You'll have to convert the dictionary into data and save it and then retrieve the data and unarchive it into dictionary.
Archive and save to UserDefaults
let myDict = [String:String]()
let data = NSKeyedArchiver.archivedData(withRootObject: myDict)
UserDefaults.standard.set(data, forKey: "myDict")
Retrieve and unarchive the data to dictionary
guard let archivedData = UserDefaults.standard.value(forKey: "myDict") as? Data
else{return}
guard let unarchivedDictionary = NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? [String:String]
else{return}
回答3:
Userdefaults not work in Playground. you need to implement and start it in an App in Simulator
来源:https://stackoverflow.com/questions/41842494/user-defaults-not-saving-dictionary-contents-in-swift-3